Should I release this property? - objective-c

I'm a objective c newbie, and i'm having a bit of problems with memory management, I've read the apple's memory management policies, however i need a bit of clarification here, this is pretty simple i guess, but i would like to ask you if I'm right:
Given this property:
#interface Test : NSObject {
NSArray *property1;
}
#property (nonatomic,retain) NSArray* property1;
#end
...
//And its implementation:
#implementation Test
#synthetize property1;
-(id) init {
if (self=[super init]) {
self.property1=[[[NSArray alloc] initWithCapacity:5] autorelease];
}
return self;
}
-(void) dealloc {
[super dealloc];
[property1 release];
}
#end
Is it right to issue an Autorelease message to the allocated object in the init method?, i do this cause in apple's document, says that every allocated object should be released by the developer, then, I think, alloc sets retain count to 1, then the property (nonatomic, retain) adds 1, so retain==2, then autorelease substracts 1, and when the dealloc method is called, property1 is released and retain count==0, am I right?

You have your memory management right, though Apple (and a lot of other people) generally recommend not using accessors in your initialization methods because accessors can have side effects beyond simply setting an instance variable that your class might not be set up to handle yet. And in that case, you wouldn't want to autorelease since you'd want ownership of the object.

one side note: in your dealloc, you need to release the property before calling [super dealloc], because [super dealloc] eventually deallocates the memory of the object, which includes the memory containing the property1 variable, so it is invalid to refer to that variable after you call [super dealloc]. It should be:
-(void) dealloc {
[property1 release];
[super dealloc];
}

One of the nice things about using properties is that you can encapsulate all of your "releasing" behavior regardless of whether your property is set to retain, copy, assign, or whatever by just doing this:
self.property1 = nil;
Personally I've gotten in the habit of setting all properties to nil (using self.property, not just accessing the member variable directly) in dealloc so that even if I change how the memory management works for the member variable it works correctly.

Related

I’ve set my property to retain, am I supposed to release it even if it is set to autorelease?

Let us say we have some code that looks like below:
#interface SomeClass : NSObject
#property (nonatomic, retain) NSString *someString;
#end
#implementation SomeClass
#synthesize someString;
-(id)init {
if (self=[super init]) {
someString = [NSString stringWithString:#"some string"];
}
return self;
}
#end
Am I supposed to release the someString property in the dealloc method of SomeClass, even if someString was set to autorelease and I never actually retained it in my init method? If so, I'd simply add [someString release] before [super dealloc] in the -release method. Correct?
Now the real issue I am having is that while using Cocos2D, I've reached a contradicting situation. My code looks like below:
#interface SomeLayer : CCLayer
#property (nonatomic, retain) CCSprite *someSprite;
#end
#implementation SomeLayer
#synthesize someSprite;
-(id)init {
if (self=[super init]) {
someSprite = [CCSprite spriteWithFile:#"SomeFile.png"];
[self addChild:someSprite];
}
return self;
}
#end
Now, I have added someSprite as a child to my layer SomeLayer. So, what should I do to make sure I have no memory leaks here? I could think of the following:
Obviously, I'd think of calling [someSprite release] in SomeLayer's -dealloc method. but it gives me EXC_BAD_ACCESS in [super dealloc] (the next line). Most likely because I didn't remove the child, and the superclass tries to access the child that I just released.
I call [self removeChild:someSprite cleanup:YES] in the -dealloc method, which would remove the child and also release it. So I do not need to follow up with [someSprite release]. But hey, the -dealloc method of the superclass CCNode already does all that for me.
I do nothing. I wouldn't override the -dealloc method at all. Well, this seems to work fine, but it contradicts the statement: "if you retain something, you're supposed to release it".
Any help on why I must release the object in case I, and why not in case II at an early stage would help save a lot of memory related issues in the long run.
Thanks
someString = [NSString stringWithString:#"some string"];
This is wrong. You are keeping a pointer to an autoreleased object that will disappear soon, and when you’ll try to use the someString pointer bad things will happen. You should use the accessor ([self setSomeString:…]), retain the autoreleased value (someString = [… retain]) or use a method that returns a retained value (someString = [[NSString alloc] init…]).
In your real use case you should do the same with the sprite, you are getting EXC_BAD_ACCESS because you over-release the sprite: you call release without ever retaining the value. Read the Cocoa Memory Management Guide, you will save yourself a lot of trouble in the long run.
By the way, I think your main problem is that you think that a simple assignment to the someString variable retains the assigned value. That is not the case (not without ARC, to be more precise). Assignment to the instance variable is just that, a plain assignment. If you want to go through the accessors, you have to send a message ([self setSomeString:…]) or use the dot notation (self.someString = …).
You only have to release objects that you explicitly allocate. None of the examples you gave were allocated, so they are autoreleased. If you want to keep an autoreleased object for a long period of time, you need to retain it, and only then you would need to release the object.
Additionally, if you have properties you should set them to nil in viewDidUnload
self.someString = nil;
You really need to read Memory Management Programming Guide.
There are two of four rules
You can take ownership of an object using retain.
When you no longer need it, you must relinquish ownership of an object you own
When you declare property as retain then you should call release for appropriate variable. In your case your dealloc should looks
- (void)dealloc
[someSprite release];
[super dealloc];
}
And look at this code
if (self=[super init]) {
someSprite = [CCSprite spriteWithFile:#"SomeFile.png"]; // here you assign pointer to new object
[self addChild:someSprite]; // all right, you can use newly created object in this scope
}
// but here that object can be deleted from memory and someSprite can points to nothing
To avoid this you need to retain newly created sprite
someSprite = [[CCSprite spriteWithFile:#"SomeFile.png"] retain];
#synthesize someSprite;
this line makes the retain count of SomeSprite to 1 ..in dealloc you release it so retain is back to 0.. object release.
[CCSprite spriteWithFile:#"SomeFile.png"];
this is an autorelease object..
when you do
someSprite = [CCSprite spriteWithFile:#"SomeFile.png"];
you point someSprite to the autorelease object.. so both are now equal..
this line messes the whole point of synthesize(retain) ..so now change this line to
[self setsomeSprite] =[CCSprite spriteWithFile:#"SomeFile.png"];
now you just continue the way it was.. have someSprite release in the dealloc.. and everything will be good again

Deallocating IBOutlets and instance vars

This is something I should have cleared up long ago, but I just need to know the best practice for deallocating in the following scenario.
In my header file I declare a reference to an IBOutlet as follows:
#interface Test : UIViewController {
UIButton *_loginBtn;
}
#property (nonatomic, retain) IBOutlet UIButton *loginBtn;
And in the implementation file I associate the instance variable to the property and deallocate as follows:
#implementation Test
#synthesize loginBtn = _loginBtn;
...
- (void) dealloc {
[_loginBtn release];
self.loginBtn = nil;
[super dealloc];
}
- (void) viewDidUnLoad {
[_loginBtn release];
self.loginBtn = nil;
[super viewDidUnLoad];
}
Am I correct in the deallocating the instance variable and setting the property to nil and doing this in both the viewDidUnLoad and dealloc methods?
There is no need for self.loginBtn = nil; in dealloc, the previous line released it. It is best not to use the property to release it in dealloc. The reason for releasing vs setting the property to nil is that the setter is a method call and the class is in the midst of tearing down and things may be unstable.
In viewDidUnLoad release any properties that are IBOutlets with self.theOutlet = nil;, in this case the _loginBtn release]; is not needed and redundant. Also release any other objects that you can easily re-create.
If properties are used they should be used for all accesses in the class with two exceptions: init and dealloc. In both of these cases the class is partially complete. In these two cases it is best to use the ivar directly in init (if necessary) and release in dealloc.
No, this is incorrect. By first releasing _loginBtn and then setting the property to nil, you release the instance twice. The correct way to do it is to release _loginBtn and then set _loginBtn to nil.

Does dealloc get called after viewDidUnload?

A quick question, after viewDidUnload does the dealloc also get called? I am asking with regards to pickerData, it was my understanding that the variable would be released when the dealloc gets called. My reason for asking is that I have noticed in one book that the author sets pickerData to nil in the viewDidUnload. Is this harmless overkill, maybe even good practice, or is there no scenario where one would not be called without the other.
INTERFACE:
#interface SingleViewController : UIViewController {
NSArray *pickerData;
}
#property(nonatomic, retain) NSArray *pickerData;
#end
IMPLMENTATION:
-(void)viewDidUnload {
[self setSinglePicker:nil];
[self setPickerData:nil];
[super viewDidUnload];
}
-(void)dealloc {
NSLog(#"Here");
[singlePicker release];
[pickerData release];
[super dealloc];
}
#end
gary
No, viewDidUnload: is called when a UIViewController's view is released. dealloc: is only called when the UIViewController's reference count goes to zero. The author's code is good practice.
The author is using synthesized methods to set the ivars to nil, which means those ivars are sent release messages. viewDidUnload: is where you're supposed to release any objects or memory you can easily recreate. The author is essentially saying, "I don't need references to these things anymore, decrement the retain count and hopefully that will free up some memory. I'll recreate it later if necessary in viewDidLoad:."
Setting the ivars to nil will have no consequences if dealloc is called as messages to nil are handled by the Objective-C runtime.

Getter Sequence Of Events?

I am trying to understand what is happening in the getter below, this is what I understand so far:
(1) the getter returns a pointer to an NSString object. (2) the NSString object is retained, possibly because we have just given away a pointer to it. (3) autorelease? when does that activate, when the PlanetClass instance is deallocated (released)?
// CLASS
#interface PlanetClass : NSObject {
        NSString *planetName;
}
- (NSString *)planetName;
- (void)setPlanetName:(NSString *)value;
#end
// GETTER
- (NSString *)planetName{
return[[planetName retain] autorelease];
}
EDIT: I think I am more confused regarding the reason for the actual retain and later release. my understanding was that the getter simply returned a pointer to either nil or an object that already exists (i.e. was set by the setter) I think I understand the retain as we are giving away a pointer and we need to track that, but what about the release, is that just a failsafe incase I later forget to release the NSString object?
The instance variable planetName is also release in my dealloc method (see below) autorelease seems to be doing the same, just later when the pool is drained?
- (void)dealloc {
[planetName release];
[super dealloc];
}
cheers -gary-
It might be a good idea to let Objective-C handle this as a property, letting you clean up some of the implementation to keep the memory management, well, manageable:
#interface PlanetClass : NSObject {
NSString* planetName;
}
#property(nonatomic, retain) NSString* planetName;
#end // PlanetClass
#implementation PlanetClass
#synthesize planetName
//... rest of PlanetClass here
#end // PlanetClass
There are plenty of docs available online for more details on Objective-C properties and #synthesize.
Memory Management Docs
I highly recommend this read from Apple on memory management to try and help understand what all the retain/release hubbub is about.
When autorelease is sent to an object, it is added to the autorelease pool. When the pool is drained, it sends release to all the objects in the pool. So any object in the autorelease pool will be release when the pool is drained
The return/autorelease in the getter method is not doing anything, you can just return planetName

I have a circular reference. How can I create a weak reference in Objective-C?

I'm working on an iPhone application. I have an object of class Row that needs to release numerous objects of the class Block. Every Block currently has a property that retains an instance variable of class Row.
#interface Block : UIImageView {
Row *yCoord;
}
#property (nonatomic,retain) Row *yCoord;
#end
Every Row contains an NSMutableArray of these Blocks.
#interface Row : NSObject {
NSMutableArray *blocks;
}
-(void)addBlock:(Block*)aBlock;
#end
#implementation Row
-(void)addBlock:(Block*)aBlock {
[blocks addObject:aBlock];
aBlock.yCoord = self;
}
#end
I understand that this is a circular reference. Apple's documentation states that in order to deallocate an object with a circular reference I need a weak reference instead of a strong reference (a retain property), but it doesn't follow through and explain how exactly I go about doing so. I plan to release and dealloc all Blocks within a Row as well as the Row itself simultaneously. How do I set up a weak reference within each of my Blocks to their "parent" Row?
Edit: Since the asker clarified he's not using garbage collection (iPhone currently does not support it), my advice is to avoid cycles by having only one of the objects retain the other, just as you would do with a delegate. When using properties, use "assign" instead of "retain" to achieve this. For example:
#property (nonatomic,assign) Row *yCoord;
The rest of my answer answer relates to "weak references" in terms of Objective-C 2.0 and GC.
When you're working with garbage collection (10.5+), a weak reference is created by prefixing a variable declaration with __weak. When you assign to that variable, the GC (if enabled) keeps track of the reference and will zero it out for you automatically if all strong references to the referenced object disappear. (If GC is not enabled, the __weak attribute is ignored.)
Thus, you can safely modify the above answer to play nicer with garbage collection (currently on 10.5+, and perhaps someday on iPhone) as follows: (See the related Apple docs.)
#property (nonatomic,assign) __weak Row *yCoord;
To quote Chris Hanson (where you can find more detailed information):
"By prefixing an instance variable declaration with __weak, you tell the garbage collector that if it's the only reference to an object that the object should be considered collectable."
I'd clarify that by saying "if there are no non-weak references to an object". As soon as the last strong reference is removed, the object may be collected, and all weak references will be zeroed automatically.
Note: This isn't directly related to creating weak references, but there is also a __strong attribute, but since Objective-C object variables are strong references by default, it is generally used only for raw C pointers to things like structs or primitives that the Garbage Collector will not treat as roots, and will be collected from under you if you don't declare them as strong. (Whereas the lack of __weak can cause retain cycles and memory leaks, the lack of __strong can result in memory stomping and really strange and insidious bugs that occur non-deterministically and can be quite difficult to track down.)
Just change it to assign instead of retain, no more circular references.
#interface Block : UIImageView {
Row *yCoord;
}
#property (nonatomic,assign) Row *yCoord;
#end
A weak reference is simply an assignment (unless you're talking about Garbage Collection which is a whole separate can of worms, but does not suffer from retain cycles).
Normally, in Cocoa, Row would retain the Block objects (by including them in the NSMutableArray), but Block would not retain Row, each would simply store it in an ivar (with an "assign" property).
As long as Row is careful to release each Block before it is deallocated (ie, its dealloc should release the NSMutableArray which will release the Blocks as long as no one else has any pointers to them) then everything will be deallocated as appropriate.
You can also take the precaution of zeroing the row reference from Blocks before removing the entiries from the array, something like:
- (void) dealloc {
for (Block* b in _blocks) {
b.row = nil;
}
[_blocks release];
[super dealloc];
}
where _blocks is the ivar referenced by the blocks property.
Using assign to create weak references can be unsafe in a multithreaded system, particularly when either object can be retained by a third object, and then used to dereference the other object.
Fortunately, this is often a problem of hierarchy, and the object containing the weak reference only cares about the object it refers to for the referred-to object's lifetime. This is the usual situation with a Superior<->Subordinate relationship.
I think that the case in the OP's comment maps to this, with Row = Superior, Block = Subordinate.
In this case, I would use a handle to refer to the Superior from the Subordinate:
// Superior.h
#class Superior;
#interface SuperiorHandle : NSObject {
#private
Superior* superior_;
}
// note the deliberate avoidance of "nonatomic"
#property (readonly) Superior *superior;
#end
#interface Superior : NSObject {
#private
SuperiorHandle *handle_;
// add one or more references to Subordinate instances
}
// note the deliberate avoidance of "nonatomic"
#property (readonly) SuperiorHandle *handle;
#end
// Superior.m
#import "Superior.h"
#implementation SuperiorHandle
#synthesize
superior = superior_;
- (id)initWithSuperior:(Superior *)superior {
if ((self = [super init])) {
superior_ = superior; // weak reference
}
}
- (void)invalidate {
#synchronized (self) {
superior_ = nil;
}
}
- (Superior *)superior {
#synchronized (self) {
// retain and autorelease is required to prevent dealloc before we're ready, thanks to AndroidDev for pointing out this mistake
return [[superior_ retain] autorelease];
}
}
#end
#implementation Superior
#synthesize
handle = handle_;
- (id)init {
if ((self = [super init])) {
handle_ = [[SuperiorHandle alloc] initWithSuperior:self];
}
return self;
}
- (void)dealloc {
[handle_ invalidate];
[handle_ release];
[super dealloc];
}
#end
// Subordinate.h
#class Superior;
#class SuperiorHandle;
#interface Subordinate : NSObject {
#private
SuperiorHandle *superior_handle_;
}
#property (readonly) Superior *superior;
#end
// Subordinate.m
#import "Subordinate.h"
#import "Superior.h"
#implementation Subordinate
// no synthesize this time, superior's implementation is special
- (id)initWithSuperior:(Superior *)superior {
if ((self = [super init])) {
superior_handle_ = [superior.handle retain];
}
return self;
}
- (void)dealloc {
[superior_handle_ release];
[super dealloc];
}
- (Superior *)superior {
#synchronized (superior_handle_) {
return superior_handle_.superior;
}
}
#end
Some advantages:
It's thread safe. There is no way you can have the weak reference contained in Subordinate become an invalid pointer. It may become nil but that is OK.
Only the objects themselves need to know about the embedded weak reference. All other objects can treat Subordinate as if it has a regular reference to Superior.