When to use Self? - objective-c

I am new to iOS development.
I have property as follows,
#property(nonatomic,retain)NSMutableArray *dataArray;
I am doing the following, to alloc it
self.dataArray=[[NSMutable alloc]init];
In the dealloc I am doing the following
-(void)delloc{
[dataArray release];
[super dealloc];
}
But I am getting memory leak for my array initialization.However , it doesn't create the
leak when I don't use self. But I wonder is it a write approach to initialise the array
without using self. Any help is appreciated.

You're getting a leak because the dataArray property is declared with retain, which means that when you use self (thus you use the setter), your retain count goes up to 2 and you only release it once. On the other hand, if you only use the ivar, the retain count is 1 (because of alloc) and you release it once, which is fine. To avoid the memory leak in the first situation, autorelease it like this.
self.data = [[NSMutableArray alloc] init] autorelease];
That will balance the retain count. As for access, except for inside the dealloc method, try to use self (setter and getter)
You should read the memory management docs, first thing to start with when developing for Cocoa Touch.
Also, why don't you use ARC?

If you use the self. signature you are accessing to the object via automatically generated / custom getter/setter. The setter will tipically manage the memory and you don't need to do that.
If you don't use self you access directly to the object.
The code what you presented is leaking, because the default setter of the dataArray will retain to the array, what you set with self.dataArray = [[NSMutableArray alloc] init];
The correct usage is:
self.dataArray = [[[NSMutableArray alloc] init] autorelease];
or:
_dataArray = [[NSMutableArray alloc] init];

What's happening here is that alloc is adding one to the retain count of the new object. The property reference is also retaining the object. If you want to do it this way, you only want one of those. A common method is:
self.dataArray = [[[NSMutableArray alloc]init] autorelease];
However, better still is to use ARC as #c.cam108 suggested and avoid the whole problem.

Related

objective c memory management in for loops

I want to execute a for loop that looks like this:
for (id object in [[MyClass methodReturningSet] allObjects]) {
//do something
}
that methodReturningSet looks something like this:
- (NSSet *)methodReturningSet {
MyObject *object1 = [[MyObject alloc] initWithCustomInfo:info1] autorelease];
MyObject *object2 = [[MyObject alloc] initWithCustomInfo:info2] autorelease];
MyObject *object3 = [[MyObject alloc] initWithCustomInfo:info3] autorelease];
MyObject *object4 = [[MyObject alloc] initWithCustomInfo:info4] autorelease];
return [NSSet setWithObjects: object1, object2, object3, object4, nil];
}
My question, is this safe in terms of memory management?
My current understanding is that 'object' will be sent a release message after the completion of the run loop.
My first question is, does the entire for loop execute within one single run loop?
My second question is, does it matter if the objects get sent release messages via the autorelease pool since the array we're looping over holds a strong reference to all the objects it contains?
hope that was clear . . . any thoughts?
My first question is, does the entire for loop execute within one
single run loop?
Yes.
My second question is, does it matter if the objects get sent release
messages via the autorelease pool since the array we're looping over
holds a strong reference to all the objects it contains?
The NSSet will retain the objects you pass to it. After adding the objects to it, you can release your own references if you don't need them anymore. This can either be normal release calls after adding them to the set (see below), or autorelease calls, as you did it. When you release the NSSet, it will also release (and in this case dealloc) all its objects.
You could use normal release messages to like this:
- (NSSet *)methodReturningSet {
MyObject *object1 = [[MyObject alloc] initWithCustomInfo:info1];
MyObject *object2 = [[MyObject alloc] initWithCustomInfo:info2];
MyObject *object3 = [[MyObject alloc] initWithCustomInfo:info3];
MyObject *object4 = [[MyObject alloc] initWithCustomInfo:info4];
NSSet *set = [NSSet setWithObjects: object1, object2, object3, object4, nil];
[object1 release];
[object2 release];
[object3 release];
[object4 release];
return set;
}
That being said, consider using Automatic Reference Counting (ARC).
My first question is, does the entire for loop execute within one single run loop?
yes.
My second question is, does it matter if the objects get sent release messages via the autorelease pool since the array we're looping over holds a strong reference to all the objects it contains?
Using autorelease or releasing the objects explicitly will not make any difference, since as you say they are also retained by the NSSet object; so the will live for the whole duration of the for loop and get released when the autoreleased NSSet returned through methodReturningSet is deallocated.
You might possibly sightly improve things if you do not autorelease that NSSet and release it explicitly just outside of the loop (but this will only make a difference if you do not immediately return after leaving the loop).

Objective-C Property assignment without #property

I'm currently developing an iOS application which was started by another developer.
Usually, I make a property for every instance variable (assign for int, bool etc. / retain for all classes).
So in my projects, this line causes a leak:
myVar = [[NSString alloc] init]; (alloc/init +1, retain in setter +1, release in dealloc -1 => +1)
So I use:
NSString *tmpMyVar = [[NSString alloc] init];
[self setMyVar: tmpMyVar];
[tmpMyVar release];
Or:
NSString *tmpMyVar = [[[NSString alloc] init] autorelease];
[self setMyVar: tmpMyVar];
In this new project, the previous developer didn't use #property/#synthesize so I'm wondering what will be the result of the previous line of code in this context (it doesn't call setter I guess)? Memory Leak?
The previous developer releases variable in dealloc method, just like me.
Thank you very much!
Since it directly assigns the instance variable to the allocated object it's retain count is 1 (because, like you said, a setter isn't called).
And because it's released in dealloc, it's all balanced out. So no memory leaks.
So in my projects, this line causes a leak:
myVar = [[NSString alloc] init]; (alloc/init +1, retain in setter +1, release in dealloc -1 => +1)
No,it wouldn't even in your projects, because, as you pointed out, no setter is used.
Also, when using properties, it is the recommended way to access instance variables directly in the init method, instead of using setters.
To inspect for questionable memory-leaks like your example, also use the clang static analyzer or instrument's leak tool.
You need to look at the other developer's setter implementation. Make sure they release the existing value and retain the new value; something like:
- (void)setMyString:(NSString *)string
{
[string retain];
[_string release]; // ivar
_string = string;
}
The only advantage to implementing your own setter/getter methods is to do something (other than setting the ivar) when a value is set. If the methods don't do anything like this then why not change all implementations to #property/#synthensize?

Managing Memory in Objective c

I am doing my project in xcode 4.2 (Older Version). For my application, I just set the variables, arrays in dto class for using in entire app lifecycle. so I set with a property like this.
AppDTO(sub class of NSObject)
AppDTO.h
#property(nonatomic,retain)anotherAppDTO *aAppDTO;
#property(nonatomic,retain)NSMutableArray *array1;
#property(nonatomic,retain)NSMutableArray *array2;
#property(nonatomic,retain)NSString *string1,*string2,*string3;
AppDTO.m
- (id)init
{
self = [super init];
if (self) {
self.aAppDTO = [[anotherAppDTO alloc]init];
self.array1 = [[NSMutableArray alloc]init];
self.array2 = [[NSMutableArray alloc]init];
self.string1 = #"Hello";
self.string2= #"Hai";
}
}
-(void)dealloc
{
if(array1 != nil)
{
[array1 release];
array1 = nil;
}
if(array2 != nil)
{
[array2 release];
array2 = nil;
}
[aAppDTO release];
aAppDTO = nil;
[super dealloc];
}
when I analyze my app in Xcode 4.3.2, I get memory warning in self.array1 and self.array2 (Potential leak on object allocated on line….), but when I change self.array1 to array1, warning goes away.
What is the reason for using self. do I need to use self if I set #property(nonatomic,retain) to variables(like array1,array2,string1,string2).
Also in dealloc method, I heard we don't want to use [self.array1 release], instead we can use [array1 release]. Is it Correct?
Do I need to release my string in dealloc method.
Also I am releasing aAppDTO in dealloc method. if I allocate some objects in anotherAppDTO class, will it release automatically when I call [aAppDTO release] method.
Can anyone clarify me.
Many Thanks,
Anish
You get the warning because when you write :
self.array1 = [[NSMutableArray alloc]init];
is the same as :
[self setArray1: [[NSMutableArray alloc]init]];
As you can notice you are not allocating the underlying array1 private variable, but you are calling the setter of the property that since it is declared as retain it retains the object once assigned, this means that when you eventually will assign another object the second time with the setter the first object will remain with a retain count of one until the application will be closed (since you don't have any reference to that object anymore ...) .
Take a look at this great article to understand better Manual Reference Counting in Objective-C .
when i analyze my app in Xcode 4.3.2, i get memory warning in self.array1 and self.array2 (Potential leak on object allocated on line….), but when i change self.array1 to array1, warning goes away.
the analyzer's right. the parameter is retained when set. as well, you should favor direct access in initialization and dealloc. so, you should just write array1 = [[NSMutableArray alloc] init];, and be done.
What is the reason for using self. do i need to use self if i set #property(nonatomic,retain) to variables(like array1,array2,string1,string2).
those go through the accessor methods. if not in initialization or dealloc, you should favor going through the accessor methods because that is the common correct execution path for a fully constructed object.
Also in dealloc method, i heard we don't want to use [self.array1 release], instead we can use [array1 release]. Is it Correct?
correct.
Do i need to release my string in dealloc method.
yes.
Also I am releasing aAppDTO in dealloc method. if i allocate some objects in anotherAppDTO class, will it release automatically when i call [aAppDTO release] method.
when its reference count reaches 0, its dealloc will be called.
I think the others have answered your question.
I do want to draw your attention to Apple's excellent Advance Memory Management Programming Guide: Practical Memory Management, in which they walk through these sorts of scenarios. It's hard to take it all in on the first reading, but it really does cover this stuff. In answer to your question about the use of instance variables versus the accessor methods, I draw your attention to the section labeled to "Don't Use Accessor Methods in Initializer Methods and dealloc".

Alloc a new objective C object to a retained property?

Sorry for asking a totally basic question, but if I have a synthesized property that is retained.
self.myProperty = [[NSObject alloc] init];
will cause a memory leak?
So am I correct in thinking that I need to do
self.myProperty = [[NSObject alloc] init];
[self.myProperty release];
in order to balance? Because that seems dumb.
Standard practice would be to use autorelease in that situation. So:
self.myProperty = [[[NSObject alloc] init] autorelease];
This is because init returns a retained object, and since your property also retains it, you'll have to release it.
Edited to add: #walkytalky makes a good point in the comments that it is actually alloc that retains the object, init just returns it.
Here is a thread that you will find helpful.
You are correct. Without ARC, any property that is retained needs to be released as well.
You can also do:
self.myProperty = nil;
From the docs:
retain
Specifies that retain should be invoked on the object upon
assignment.
The previous value is sent a release message.
Another (more verbose) technique is to do:
NSObject *o = [[NSObject alloc] init]; //retain count 1
self.myProperty = o; //retain count 2
[o release]; //retain count 1
Personally though, I'd probably just use autorelease as in the first example above.
With ARC enabled, xcode will handle alle the memory management.
When not using ARC be sure to release it in the dealloc method.

Why always leak when using CLLocationManager?

myclass.m
- (id) init {
self = [super init];
if (self != nil) {
self.locationManager = [[[CLLocationManager alloc] init] autorelease];
self.locationManager.delegate = self; // send loc updates to myself
}
return self;
}
- (void)dealloc {
[locationManager release];
[super dealloc];
}
I use instrument to check leak. The leak always point to
self.locationManager = [[[CLLocationManager alloc] init] autorelease];
Why?
I use instrument to check leak. The
leak always point to
self.locationManager = [[[CLLocationManager alloc] init] autorelease];
Why?
Because that is the line of code where the allocation that is leaked occurred. Since you have balanced both implied retains in that code correctly (once here, once in -dealloc -- mmccomb's suggestion of direct assignment without autorelease is good, but won't fix the problem), the leak is elsewhere.
Specifically, the leak will be a retain that isn't balanced by a release. So, somewhere your are retaining the object and not releasing it.
Instruments can be used to show all retain/release events on any given object. Use that and look through the list of events related to your leaked object. There will be one more retain than release. Pair off the retains and releases. Whichever retain is left without a balanced release is the cause.
I wrote an article about using Heapshot analysis in Instruments to detect memory abuse. It includes discussion and screenshots showing the retain/release event inspector and will be applicable.
Try to avoid using the self. setter notation in init methods. When an object is being initialised there is no guarantee that it is in a consistent state. Change your implementation to directly set the ivar as follows...
locationManager = [[CLLocationManager alloc] init];
You no longer need the autorelease call which was previously accounting for the extra retain count brought about by invoking the setter. You do however need to release the object in your dealloc method (as you are already doing).
You can explicitly check the retain count in dealloc like so:
NSLog(#"locationManager retain count: %d", [locationManager retainCount]);
If it is more than 1, check where else you may be retaining it - like if you assign it to another retaining property (e.g. declared with retain keyword). You can add that NSLog call in other locations before and after you do something with locationManager and see where the retain count increases. Sometimes it may not be immediately obvious.
Another possibility: does the dealloc method even get called? Perhaps the whole "myclass" object is not properly released? (Although I suppose in that case you'd see a leak of type "myclass", too).