Use autorelease when setting a retain property using dot syntax?
Asked Answered
C

2

6

I see in some sample code that autorelease is used. I am not familiar with the instances when this is required. For example, if I create an annotation object

Header file

@interface someViewController: UIViewController 
{
    Annotation *annotation;
}

@property (nonatomic, retain) Annotation *annotation;

@end

Implementation file

@implementation someViewController
@synthesize annotation
@end

Question: Is it the correct approach if I initialize my annotation object in the implementation file like this?

self.annotation = [[Annotation alloc] initWithCoordinate:location];

Do I need to set autorelease for this? Or can I just do it the normal way and add the release in the dealloc method?

Cab answered 19/5, 2011 at 7:33 Comment(1)
Possible duplicate of Autorelease vs. release and there are many, many other questions that will answer this if you take the time to read them: Search: iPhone retain property autorelease This: Release/autorelease confusion is probably one of the best.Rida
W
15

this is correct:

self.annotation = [[[Annotation alloc] initWithCoordinate:location] autorelease];

because annotation property is declared as a retain property, so assigning to it will increment its retain count.

you will also need, all the same, to release self.annotation in -dealloc.

in short:

  1. init will set retain count to 1;

  2. assigning to self.annotation, will set it to 2;

  3. autorelease will set it back to 1 when the main loop is executed again;

  4. release in dealloc will set the retain count to 0, so that the object will be deallocated);

the best way to think of autorelease is the following, in my opinion: autorelease will "schedule" an "automatic" release for your object at some (near) point in future (typically when the control flow goes back to the main loop, but details are hidden in the hands of Apple).

autorelease is mostly useful in conjunction with init, specifically in the following cases:

  1. when you init a local variable, so that you don't have to release it explicitly before it goes out of scope (the main loop will do that for you);

  2. when you return a pointer to an object you have just created without keeping ownership of it (typical case of the create/make* kind of selectors, the receiver is required to retain it to get ownership);

  3. with properties that retain, when you assign to them an object that they should own uniquely;

  4. with data structures that increment the retain count (NSMutableArray, NSMutableDictionary, etc): you should generally autorelease a newly inited object when you add it to such data structure.

apart from case 2, it is evident that the use of autorelease is meant to improve readability of the code and reduce the potential for errors (meaning that in all of the other cases, you could simply release explicitly your object after the assignment or at the end of the scope).

when using properties, you have always to check whether they are of the retain or assign/copy case; in the first case, assigning a newly inited object to a property generally requires autorelease.

Anyway, I would suggest at least skimming one of the many tutorial on memory management for iOS.

Williawilliam answered 19/5, 2011 at 7:37 Comment(1)
One quick gotcha, if you write annotation = [[Annotation alloc] initWithCoordinate:location]; without the self the retain count will not increase.Rufus
C
2

Autorelease is telling the object to release itself before leaving the scope.

Sometimes when you code, you'll encounter something like this

- (void)doSomething
{
    if(true)
    {
        NSString *foo = [[NSString alloc] initWithString:@"foo"];

        //Some execution here

        [foo release];
    }
}

- (void)doSomething
{
    if(true)
    {
        //By doing this is telling to to release foo object before getting out of the scope
        //which is similar with above practice
        NSString *foo = [[[NSString alloc] initWithString:@"foo"] autorelease];

        //Or you can do it this way
        NSString *foo = [[NSString alloc] initWithString:@"foo"];
        [foo autorelease];

        //Some execution carry on, it'll release foo before entering next scope

    }

//This is out of the scope }

Of course, releasing an object doesn't mean deallocating the object. Sometimes you retain the object so you can still use it outside of its scope.

Judging from your question, if your the object is located within your header file/interface. You should release it in dealloc method. CMIIW.

Counterproductive answered 19/5, 2011 at 7:50 Comment(2)
just to clarify, my understanding is that even if the object is in the header file, we might still need to execute autorelease if for example self.annotation = [[Annotation alloc]init... happens. Is that correct?Cab
@Cab usually you'll initialize your interface object (even making it nil). Thus releasing in dealloc is a must. But if by some chance you init your object again (which will cause memory leak because you lost your previous memory address), yes, you can set autorelease. Remember when we alloc and init, we're talking about memory address. This is what I know, you can read/ask experienced programmer if you wish to learn more.Counterproductive

© 2022 - 2024 — McMap. All rights reserved.