Objective C - Core Data memory management? - iphone

1- Is these anything wrong with the way
i am deallocing the object?
2- Does my dealloc override the dealloc
for NSManagedObject?
3- Do i need to dealloc super even
though my object is an
NSManagedObject type and core data ia
responsible for it?
#interface MyClass : NSManagedObject
#property (nonatomic, retain) NSString *coreDataString;
#property (nonatomic, retain) NSNumber *coreDataNumber;
#property (nonatomic, retain) CoolObject *coolObject;
#end
.
#implementation MyClass
#dynamic coreDataString;
#dynamic coreDataNumber;
#synthesize coolObject;
- (void)dealloc
{
[self.coolObject release];
}
#end

Yes, you are not calling [super dealloc].
Yes.
Yes, you must always call [super dealloc] at the end of your dealloc method. Otherwise memory will not be freed correctly.

You should call release on the member variable directly instead of using the property. You also should still call the super dealloc. So your dealloc would look like this:
- (void)dealloc
{
[coolObject release];
coolObject = nil;
[super dealloc];
}
Otherwise, you can set the property to nil which will automatically release the local variable if necessary. The above way is preferred so you don't accidentally run a complicated function that could be overriding the property's setter.

You should always call [super dealloc] in the dealloc method. But in subclasses of NSManagedObject you should never use the dealloc method at all. use - (void)didTurnIntoFault instead.

You are overriding the parents - (void)dealloc method. When you override a parent object's method, the parent's method is never called until you explicitly call the super's method. In your case, the parent's - (void)dealloc is not called. To fix this, you must call [super dealloc] to ensure that the parent's instance variables are deallocated too.

Related

iPhone Properties

I a few simple questions to make sure I am using properties right in my application. I read a lot online but it is still unclear. Thanks a lot for any help or suggestions.
(1) I am not quite sure that the statement does, and why is it needed.
#synthesize personName = _personName;
Why do you need the _personName variable? What is the benefit of doing that as opposed to just creating a property and synthesizing that variable personName.
#property (nonatomic, retain) NSString *personName;
(2) In my application should I be accessing the property variable self.personName or use the _personName variable. I believe the self.personName is correct by then again why is the _personName even there?
(3) Also I am a little confused to which variable I should release in dealloc() and which variable should I set to nil in viewDidLoad(). I also do not know if any changes should be made to the didReceiveMemoryWarning() method.
#interface ViewController : UIViewController
{
NSString *_personName;
}
#property (nonatomic, retain) NSString *personName;
#end
#implementation ViewController
#synthesize personName = _personName;
- (void)viewDidLoad
{
[super viewDidLoad];
self.personName = [[NSString alloc] initWithString:#"John Doe"];
NSLog(#"Name = %#", self.personName);
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
}
- (void)viewDidUnload
{
[super viewDidUnload];
}
- (void)dealloc
{
[super dealloc];
}
#end
#synthesize personName = _personName;
That statement creates the accessor methods for the personName property. You've specified that the accessors should use an instance variable named _personName. If you just had #synthesize personName;, the accessors would use personName as the instance variable instead.
You should usually use the accessor methods, as in self.personName or somePerson.personName or somePerson.personName = #"Joe";. If you don't care what the name of the ivar that backs up the personName property, you don't need to specify it.
Use the accessors in -viewDidLoad, as in: self.personName = nil;. Same for -didReceiveMemoryWarning:. Whether to use the ivar or property in -dealloc is debatable, and to some degree a matter of taste. The main concern with using the property accessors in -dealloc is that it can cause problems if your class is subclassed and the accessors are overridden. Often, you don't need to worry about that because you know that your class won't be subclassed.
Setting an ivar to nil after releasing is also debatable. Many people feel that it's good style to do so, others feel like it's a waste of time. Use your best judgement. It's certainly not necessary, but rather something that some feel is a matter of good housekeeping.

Am I leaking this ObjectiveC Object?

#interface foo: NSObject
#property (nonatomic, retain) NSMutableArray *aMutableArray;
#end
#implementation
#synthesize aMutableArray
-(void)somefunction {
// Illustration
self.aMutableArray = [[[NSMutableArray alloc]init]autorelease];
self.aMutableArray = [[[NSMutableArray alloc]init]autorelease];
self.aMutableArray = [[[NSMutableArray alloc]init]autorelease];
}
#end
I have done code similar code to this in other parts of my program, but I needed to be certain that this does not cause a memory leak. With my understanding of autorelease, this object is released correctly right?
[EDIT - added question]
One question though: the property above has a retain attribute, so when the compiler creates the setter function, the setter code will look something like this:
somecode..
retain newObj
release oldObj
somecode..
in the code above, I assigned 3 objects to aMutableArray.
Each time they are assigned, the setter function did a retain on the newObj and a release on the oldObj. So, since the setter method already did a release, will there be a problem when the autorelease kicks-in to release the object a second time?
Yes, it will be released correctly if you also release it dealloc method:
- (void) dealloc{
[aMutableArray release];
[super dealloc];
}
Note also that you can shorten your code using equivalent convenience +array method of NSMutableArray:
self.aMutableArray = [NSMutableArray array];

When is the proper time to release an object?

I'm still a little confused on this.
I'm creating an object programmatically in Xcode, let's say a UILabel, which is also going to be a class wide property.
When is the proper time to release the object, in the method in which it is created, or in the dealloc method like normal IBOutlet objects?
Thanks.
This depends on whether your property is set to retain the value or not. Usually you want the accessors (generated by #synthesize) to handle the retain/release when the property is set to a new value. You specify such a property like this:
MyController.h
#interface MyController : UIViewController {
UILabel *myLabel;
}
#property (nonatomic, retain) UILabel *myLabel;
#end
You can then use #synthesize to generate the default getters and setters. The default setter for a 'retain' property will release the current value and retain the new value. However, nothing is done for you in dealloc. Meaning, that when the controller is destroyed, your reference to you label will leak since release will not be called. For this reason, you need call release on all your 'retain' properties in dealloc, like this:
MyController.m
#implementation MyController
#synthesize myLabel;
-(void) dealloc {
self.myLabel = nil;
[super dealloc];
}
#end
Notice that in this case, self.myLabel = nil is almost equivalent to calling [myLabel release] since the setter will call release on the existing value and then call retain on the new value. Since the new value is nil, calling [nil retain] has no effect. I prefer to nil instead of releasing since you are also setting the ivar to nil and avoids dangling pointers.
When you create a property like this programmatically as opposed to from Interface Builder, you don't need to mark it with IBOutlet. In the cases where you do create a control using IB, you should nil all of your IBOutlet references in viewDidUnload. This is because your control could be deallocated along with the view if it wasn't retained. Referencing it afterwards will crash the app so it's a good practice to nil them, like this:
- (void)viewDidUnload {
[super viewDidUnload];
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
self.myIBLabel = nil;
}
Another common mistake that happens when using properties is to omit the 'self' part. If you do not use the self.myIBLabel notation, you are bipassing the getter and setter and working with the ivar directly. This will NOT retain/release the object.
You should release it in the dealloc method, although that depends how you're creating your class property.
If you release it in the method in which you create it, and then use it in some other part of your class (which, since you're making the UILabel a class wide property, I assume you are), you will get a bad access when you try to modify it later on. Note that if you're using a retained property you need to take that into account, in which case you might release the label (because you'll have created it and assigned it to your class property, which will retain it again).
Here's a typical example:
- (void) someMethod {
UILabel *myLabel = [[UILabel alloc] initWithFrame:myFrame];
self.textLabel = myLabel;
[myLabel release];
}
- (void) dealloc {
[textLabel release];
}

Setting a object with "Assign" property to nil

If I am having a variable defined with "Assign" property then is it ok to setting them to nil in dealloc method?
#property (nonatomic, assign) id test;
- (void)dealloc {
self.test = nil;
}
It's better to release the ivar directly. If a subclass overrides the setter methods of a property, your object might leak because your setter is not called. Consider:
#interface ClassA
#property (readwrite, retain) id anObject;
#end
#interface ClassB : ClassA
#end
#implementation ClassA
#synthesize anObject;
- (void)dealloc {
self.anObject = nil;
[super dealloc];
}
#end
#implementation ClassB
- (void)setAnObject: (id)anObject {
// do nothing!
}
#end
Instances of ClassB will leak anObject!
Depends how you do it, if you do it via the property setter (not recommended), then yes.
If you do direct assignment, then no, because the retained object will leak.
So this is fine:
- (void) dealloc {
self.test = nil;
[super dealloc];
}
But this is a no-go:
- (void) dealloc {
test = nil;
[super dealloc];
}
My advice is to just send the release message to all of your retained ivars in -dealloc, this will work nicely because if test happens to be nil, then nothing will happen.
Trust me. Send release directly in -dealloc. That is all.
- (void) dealloc {
[test release];
[super dealloc];
}

iOS initWithCoder/decodeObjectForKey memory leak

The Leaks instrument tells me that I have a memory leak when I use decodeObjectForKey within initWithCoder. For example:
Class.h
{
MyObject *myObject;
}
#property (nonatomic, retain) MyObject *myObject;
Class.m
#synthesize myObject
-(void)dealloc{
[myObject release];
[super release];
}
-(id)initWithCoder:(NSCoder *)decoder{
if (self = [super init]{
self.myObject = [decoder decodeObjectForKey:#"MyObject"];
}
return self;
}
Per request in the comments:
-(void)encodeWithCoder:(NSCoder *)encoder{
[encoder encodeObject:myObject forKey:#"MyObject"];
}
Leaks reports a leak of type NSCFString on the line;
self.myObject = [decoder decodeObjectForKey:#"MyObject];
As I understand it, decodeObjectForKey returns an autoreleased object. Since I immediately assign that value to the myObject property, which is specified as (nontoxic, retain) in the property definition, I retain the autoreleased object through the setter method of the myObject property. The myObject is then released in the dealloc method. I don't understand where the leak is if I understand the sequence correctly. Also why is it reported as a NSCFString when the type is MYObject?
Any thoughts would be appreciated, including if my assumptions above are correct.
Look carefully at your -dealloc method. You are calling [super release]; when you should be calling [super dealloc];.
Calling [super release] in this case is the same thing as calling [self release], since you're not overriding the -release method. If your -dealloc method is called, your object has already been fully released, so this is unnecessary. Since you are overriding the -dealloc method, you must call [super dealloc] to also free any memory allocated by the superclass.
You can refer to the NSObject documentation to see how to override dealloc correctly.