Is the Object retained in this case - iphone

I have a simple question, that in a class I have a variable with property retain
//Classs ArrayClass has this array
#property(nonatomic, retain) NSMutableArray *array;
Now when I do
self.array = [SomeClass getArray];
I need to release the array...
Now If I have object of ArrayClass and when I do
arrayClassObj.array = [SomeClass getArray];
So in this case, Is the setter method is called? Do I need to release in this case.

The setter generated by #synthesize will (since you told it to retain) handle the retaining and releasing for you. If you override it, it's on you.
In your dealloc, don't forget to release it as well -- safe, don't forget, because messages to nil are not errors (and you should be setting a var to nil if you're through with it).

In both cases the object being assigned it's array property from [SomeClass getArray] will need to release it itself, unless you set the property to nil.
The following is required by the class owning the array property.
// ArrayClassObject dealloc (self in first example)
-(void)dealloc
{
[array release];
[super dealloc];
}
When you assign the property then assign it nil, the [array release] is still required in the dealloc method, but since you're assigning nil to it, it won't have any effect.
// someArrayObj must have [array release] in its dealloc method
someArrayObj.array = [SomeClass getArray];
// But you can do it manually by assigning nil
someArrayObj.array = nil;

Related

Avoid Memory Leak When Property Assigning Twice

Let say i have an class named as MyTestClass.h.
Class structure is look like
#interface MyTestClass : NSObject {
NSString *testString;
}
#property (nonatomic, retain)NSString * testString;
#end
.m file
#implementation MyTestClass
#synthesize testString;
-(id) init{
[self setTestString:#""];
return self;
}
-(void)dealloc{
[self.testString release];
testString = nil;
[super dealloc];
}
#end
Now i created an object of MyTestClass and assigned testString twice
MyTestClass * myTestClass = [[MyTestClass alloc] init];
[myTestClass setTestString:#"Hi"];
[myTestClass setTestString:#"Hello"];
Now i think, two times my testStrings memory is leaked!! (one through init() and another one through my first setTestString method)
Am i correct? or will #property (nonatomic, retain) handle/release previous allocated memory?
or ,in this kind of cases ,will i need to override the setTestString() in MyTestClass.m like below code
-(void)setTestString:(NSString *)tempString{
[testString release];
testString = nil;
testString = [tempString retain];
}
Any help on this question is appreciated.
Thanks.
Any help on this question is appreciated.
I'll take this as a licence to make sone observations not necessarily directly related to your question.
Firstly, if you declare a retain property (as you have done) and synthesize it, the automatically generated getters and setters handle memory management correctly for you.
If you manually create setter (which you are allowed to do even with an #synthesize existing), you have to do the memory management yourself. Use either of trojanfoe's examples.
The setter in your question contains a bug in that if testString == tempString i.e. you assign the value of the property to itself, you could end up with assigning a dangling pointer to the property because you effectively release tempString and then retain it.
This is an implementation detail that you an safely ignore, but string literals e.g. #"blah" are compiled into the executable and will never be deallocated no matter how many times they are released. So, with your example, even if the setter did not do correct memory management, there will be no leak.
By the way, the normal pattern for an init method is
-(id) init
{
self = [super init];
if (self != nil)
{
// init stuff
}
return self;
}
or logical equivalent.
You should get into the habit of using it because you need to call the super class's init method and it is allowed to change the value of self, even to nil.
Also, while it is very good practice normally to set the object reference to nil after releasing it, in both cases when you do it, it is unnecessary. the first time, the variable is about to go out of scope and the second time you immediately assign it from some other object.
It's not a leak. Synthesized variable are correctly handled.
A synthesized method is implemented in this way (for a retain keyword)
#property (nonatomic, retain) NSString *string;
//backed by variable NSString *_string;
- (void)setString:(NSString*)newString
{
if (newString != _string) {
[_string release];
_string = [newString retain];
}
}
Of course this is a leak:
- (void)aMethod //of my class with string property
{
NSString *aString = [[NSString alloc] initWithString:#"hello"];
self.string = aString; //retain count of 2
self.string = #"hello2"; //retain count of 1 for aString
//now I don't release aString.... leak
}
If you use the auto-generated setter (in your case, setTestString:, which is also called by self.testString = ...;), the previous value of a retain property is released before being set. So no, there is no leak in the code you posted above.
The synthesized setter method should do the right thing. Here's an example of it's implementation:
- (void)setTestString:(NSString *)tempString
{
[tempString retain];
[testString release];
testString = tempString;
}
or:
- (void)setTestString:(NSString *)tempString
{
if (tempString != testString)
{
[testString release];
[tempString retain];
testString = tempString;
}
}
the dealloc is only called when the instance is destructed.
if you do :
[myTestClass setTestString:#"Hi"];
[myTestClass setTestString:#"Hello"];
in the same block, you're juste calling twice the setter. there is no memory leak.
When you use #synthesize on a property that specifies retain, the setter that's generated will handle the retain/release correctly for multiple assignments. As long as you use self. rather than going directly to the backing variable and do a final release in dealloc you should be fine.

Autorelease and properties

I have few questions to ask about the following class
#import <Cocoa/Cocoa.h>
#interface SomeObject {
NSString *title;
}
#property (retain) NSString *title;
#end
implementation SomeObject
#synthesize title;
-(id)init {
if (self=[super init])
{
self.title=[NSString stringWithFormat:#"allyouneed"];
}
return self;
}
-(void)testMethod{
self.title=[[NSString alloc] init] ;
}
-(void)dealloc {
self.title=nil;
[super dealloc];
}
In the .h file do we need to declare the title and sub when we add the property. is it not enough to add the #property (retain) NSString *title; line.
2.Do i need to autorelease both assignment to title in the init and testMethod. if So why?
Can some one explain these things to me.
1-
You don't need to declare the iVar in the header. You might also use
#synthesize myVar = _myVar;
if you want to go for a different iVar name
2-
Declaring a property "retain" means that every time you assign the property with a new object, it automatically releases the previous object and retain the new one.
Therefore, if you use a convenience method like stringwithFormat, the property will retain that object for you.
If you want to use alloc-init, for me the best way to do is:
NSString *str = [NSString alloc] init];
self.title = str;
[str release];
Besides, it is right to assign nil to the property in the dealloc because the property will release the object it has, and it calls retain on nil which doesn't do anything
1.No need to declare title in .h, declaring property is enough.
2.when you are using self.title in init, you do not have to autorelease it.But when you initialize it in testMethod, you need to autorelease it because you have declare the property as retain.And do not forget to release title in dealloc.
you don't need to add as it is done automatically (Since Xcode 4 I guess).
in init- you don't as it already returns an autoreleased object..
where as in testMethod you need to since you are allocating it..
you always have to release any object which you create using alloc , copy or new .... AMEN.. :)
Be aware it is not considered a good practice to use accessor methods in initializer methods and dealloc method. Do check out this answer: Why shouldn't I use Objective C 2.0 accessors in init/dealloc?
Also in Apple's memory management guide: https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/MemoryMgmt/Articles/mmPractical.html

When to release and how to use these instance variables to avoid memory leaks?

I'm new in iPhone development and after reading Apple documentation and several posts here I still have some doubts about memory management. Please, supouse this basic class:
//MyClass.h
#interface MyClass : NSObject {
NSString *varA;
OtherClass *varB;
NSString *varC;
NSString *varD;
}
#property (nonatomic, copy) NSString *varA;
#property (nonatomic, retain) OtherClass *varB;
#property (nonatomic, copy) NSString *varC;
#property (nonatomic, copy) NSString *varD;
+ (id) initClass:(NSString *)desc;
- (void) method1:(NSString *)desc;
#end
With this implementation:
//MyClass.m
#implementation MyClass
#synthesize varA;
#synthesize varB;
#synthesize varC;
#synthesize varD;
+ (id) initClass:(NSString *)desc{
self = [super init];
if( self ){
self.varA = [NSString stringWithString:desc];
self.varB = [OtherClass initClassWithAutorelease:#"a description"]; //this class return an autoreleased object
[varB aMethod:#"something"];
}
return self;
}
- (void) dealloc{
[varB aMethod:#"something"];
[varA release];
[varB release];
[super dealloc];
}
- (void) method1:(NSString *)aString{
self.varC = aString;
self.varA = [NSString stringWithString:#"new value"];
[varB aMethod:#"something"];
}
#end
At this point what I have in mind is that the instance variables with #property have to be use without self. in the init method of the class and release them without self. in the dealloc, in other methods it is convinient to use self. for all cases. So here are my doubts:
First, I suppose that if I use self.varA= in the init method the retain counter increase so I have to release it in the dealloc method, even if the object has not been created with alloc, copy or new. Or I can use only varA= in the init and I will not need to do a release. For other class methods it's better to use the setter/getter so I can use self.varA=, ... appendString:self.varA ... or ...=self.varA without problem. Is all this correct?
Second doubt, what is best in terms of memory management and simplicity, to assign to an instance variable an object in the init method with or without autorelease? If I assign to it one without autorelease I will have to dealloc it but if I use autorelease the variable could be released before I want (like the autoreleased self.varB = [OtherClass... that will be used in the dealloc method whenever the MyClass is released).
Third, do I have to dealloc all my instance variables even if I don't use them in the init method but I could use them (read/write) in other methods of the same class? (Like varC in method1 or varD that is not used).
Fourth, do I need to take care of varA after assigning the new value in method1 if I did it well in the initClass and dealloc methods? In other words, will this generate memory leaks?
Fifth, if I declare with autorelease this class like an instance variable in a ViewController (MyClass *c; ... c = [[[MyClass alloc] initClass:#"description"] autorelease];) and I set the #property, do I have to do a release if I use it with c=... instead of self.c=...? As far as I know the behavior is the same than in my example so I should use the setter/get method in the viewDidLoad or viewWillAppear and released it in the dealloc without self..
Sixth and last one, for a instance variable is varA the same that self->varA?
Thanks...
At this point what I have in mind is that the instance variables with #property have to be use without self in the init method of the class and release them without self in the dealloc
This is completely the opposite of what is true. #property just makes the variable public outside of the class. If you have another class call that object, it will look in the header file (.h file), if it doesn't see a variable by that name, it will throw a warning during compile, and an error during runtime. When using properties with synthesize (btw, your synthesize can be all on one line, doesn't really matter though, ex: #synthesize varA, varB, varC;), using self automatically retains and keeps a retain count.
- (id) initClass:(NSString *)desc{ //Note the "-" instead of the "+" here, this is an instance method, not a class method
self = [super init];
if( self ){
[self setVarA:[NSString stringWithString:desc]];
[self setVarB:[OtherClass initClassWithAutorelease:#"a description"]];
[varB aMethod:#"something"];
}
return self;
}
in other methods it is convinient to use self for all cases.
Very untrue as well. If anything, this adds another call to the call stack and makes the execution slower (by one operation, but still, one more than needed). Consider this example:
[[self varA] doStuff:#"OMG"];
versus
[varA doStuff:#"OMG"];
The 2nd one will only access one pointer, where as the first one will have to access 2 pointers to get to the same result.
First, I suppose that if I use self.varA= in the init method the retain counter increase so I have to release it in the dealloc method, even if the object has not been created with alloc, copy or new.
Untrue. The class handles the first retain, and because of this, it handles a release as well. When your class is released, it sends a release to everything it has a retain on. If you do a release in your dealloc, this will actually decrease its retain count to -1 and create a memory error. If you set the property with self.varA = someObject, then it will give it a release when your class is dealloced. If you did self.varA = [someObject retain], then you would have to do a release in the dealloc.
Or I can use only varA= in the init and I will not need to do a release.
Kinda true, you would not need to do a release because you did not do a retain. But if something else lowers the retain count to 0 on this object, there is nothing in your class that forces the object to stay alive, and it will be freed, and if you reference it, memory error.
For other class methods it's better to use the setter/getter so I can use self.varA=, ... appendString:self.varA ... or ...=self.varA without problem. Is all this correct?
No, see why above. Only use [self setVarA:newValue] if you are changing the instance of the object, the synthesize will handle the rest. Otherwise just use [varA value] to get what ever data you need.
Second doubt, what is best in terms of memory management and simplicity, to assign to an instance variable an object in the init method with or without autorelease? If I assign to it one without autorelease I will have to dealloc it but if I use autorelease the variable could be released before I want (like the autoreleased self.varB = [OtherClass... that will be used in the dealloc method whenever the MyClass is released).
If you are creating a new object in init, autorelease it. You will have to release it in your dealloc if you do just a regular alloc init. The variable will not be released before you want it because of the retain you do on it through the property. EX
-(id) init {
self = [super init];
if(self) {
[self setVarA:[[[NSString alloc] init] autorelease]]; //Sets a new instance of NSString, autoreleased
}
return self;
}
This is correct, you do not need to do anything in your dealloc. You are creating an object with a retain count of 2 (one for the alloc you did here, and 1 for the retain you do when the synthesize sets the value in your class). Now, if it autoreleases, its retain will only go down by 1, and you will still have the retain from your property, so it will not release before your class releases
-(id) init {
self = [super init];
if(self) {
[self setVarA:[[NSString alloc] init]]; //Sets a new instance of NSString
}
return self;
}
Again, you create an object with a retain count of 2. You will need to do a [varA release] in the dealloc to knock the retain count down enough for it to be released when your class is released.
Third, do I have to dealloc all my instance variables even if I don't use them in the init method but I could use them (read/write) in other methods of the same class? (Like varC in method1 or varD that is not used).
No, you do not want to send releases to freed objects. You really should never use a dealloc in my opinion, but if you decide you want to for sure, then the worst case is to check to see if the object is null, and if its not, then release it
if(varD != null)
[[self varD] release];
Fourth, do I need to take care of varA after assigning the new value in method1 if I did it well in the initClass and dealloc methods? In other words, will this generate memory leaks?
No memory leaks from NSString. This method returns an autoreleased object. When you assign a new value to [self varA], it will release the old object, and retain the new object.
Fifth, if I declare with autorelease this class like an instance variable in a ViewController (MyClass *c; ... c = [[[MyClass alloc] initClass:#"description"] autorelease];) and I set the #property, do I have to do a release if I use it with c=... instead of self.c=...? As far as I know the behavior is the same than in my example so I should use the setter/get method in the viewDidLoad or viewWillAppear and released it in the dealloc without self..
You don't need a release in either scenario. The alloc increases the release count by 1, the autorelease will decrease it to 0. If you did self.c, that would increase it to 2, and decrease to 0 (one decrease from autorelease, and one from the property) when your class is released. You do not need to do ANYTHING in dealloc.
Sixth and last one, for a instance variable is varA the same that self->varA?
Yes, they point to the same location in memory.
when ever you write "alloc, retain, copy, new" you are responsible for releasing them in the dealloc method. ex
.h file
NSString * string;
#property (nonatomic, retain)NString * string;
.m file
#synthesize string;
-(void)dealloc{
[string release];
}
hope that helps :D

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];
}

Iphone Right way to set a property

i have the following code in .h:
#property (nonatomic, retain) NSArray *arrayData;
And in the .m in method initWithNibName:
self.arrayData = [NSArray arrayWithObjects:#"Usuario:",#"Password:",nil];
is it right in order to call
[self.arrayData release]
safely in order to release the object?
No, it is not correct to call release on your property. The problem with it is, that you release your property, it will get deallocated, but you didn't set your pointer to nil, so somebody might send a message to your property and get a crash.
What you can do is the following:
self.arrayData = nil; ( which will release the previous saved instance, and set the property to nil)
[arrayData release]; arrayData = nil; (here you are accessing your ivar instead of your property; setting your ivar to nil is a precaution)
[self->arrayData release]; self->arrayData = nil (this is exactly the same as #2)
Hope this helps.
You need to call:
[arrayData release]
Calling [self.arrayData release]; will not have the effect you want it to in either case.
If you're wondering why this is, check this question out: difference between [self.property release] and [property release]
A)
it is a bad idea to do this in your initializer (e.g., initWithNibName:bundle:)
self.arrayData = [NSArray arrayWithObjects:#"Usuario:",#"Password:",nil];
use this instead:
arrayData = [[NSArray alloc] initWithObjects:#"Usuario:",#"Password:",nil];
you should not call these accessors (properties) in initializers or dealloc.
B)
is it right in order to call
[self.arrayData release]
no. in many cases (assuming you implement some of the properties you've declared), you may not be returned the the ivar. you may receive a copy, a placeholder object, or a subclass may have chosen to re-implement the accessors (as some examples). in these cases, it's easy to over-release or over-retain (resulting in evil stuff, like leaks and crashes).
this is typical:
self.arrayData = nil;
unless you are in dealloc of the object which declared the ivar:
- (void)dealloc {
[arrayData release], arrayData = nil;
[super dealloc];
}