开发者

Understanding memory management in Objective-C

I've got the following code that works OK, but I'm not sure if I understood correctly some memory management concepts:

#import "mapPoint.h"

@implementation mapPoint
@s开发者_如何学Cynthesize coordinate, title, subtitle;

-(id)initWithCoordinate:(CLLocationCoordinate2D)c title:(NSString *)t {
    [super init];
    coordinate = c;
    [self setTitle:t];
    // Set date as subtitle
    NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
    [dateFormatter setDateStyle:NSDateFormatterMediumStyle];
    [dateFormatter setTimeStyle:NSDateFormatterShortStyle];
    NSString *myDate = [dateFormatter stringFromDate:[NSDate date]];
    [self setSubtitle:myDate];
    [dateFormatter release];
    // Look for city and state; when found, set it in subtitle, replacing date
    geocoder = [[MKReverseGeocoder alloc] initWithCoordinate:c];
    [geocoder setDelegate:self];
    [geocoder start];
    return self;
}
-(void)reverseGeocoder:(MKReverseGeocoder *)geocoder didFailWithError:(NSError *)error {
    NSLog(@"%@", error);
}
-(void)reverseGeocoder:(MKReverseGeocoder *)geocoder didFindPlacemark:(MKPlacemark *)placemark {
    [self setSubtitle:[NSString stringWithFormat:@"City: %@, State: %@", [placemark locality], [placemark administrativeArea]]];
}
-(void)dealloc {
    [title release];
    [subtitle release];
    [geocoder release];
    [super dealloc]; 
}

@end 
  1. As I created the geocoder object via the alloc method, I have to release it (done in dealloc). Correct?
  2. In method reverseGeocoder:didFindPlacemark a NSString is created with the convenience method stringWithFormat. As I didn't use alloc, I'm not responsible for releasing that (I assume that method uses autorelease). Is that right?
  3. The object placemark returns two NSStrings, locality and administrativeArea. Again, I didn't create those strings, so I'm not releasing them. However, given that they are part of the subtitle property of my mapPoint object, I don't want those strings to disappear, but they probably were created with autorelease. The property subtitle is declared with retain. Is is correct to assume that it will retain the NSString created with the convenience method, preventing it's premature destruction?

Thanks, and apologies if the questions are complicated... the subject is.


  1. geocoder is an ivar in your class? Then your code is correct. Note that, since the geocoder is useless after it returns a result, you could release it (and set the ivar to nil) in the appropriate delegate methods to allow the memory to be reclaimed earlier.
  2. Correct, mostly. If you had used a method starting with "new" or containing "copy" to get the instance of the object, you would also be responsible for releasing it.
  3. Correct on all points. Note that if you were to implement setSubtitle: yourself instead of allowing @synthesize to do it, you would be responsible for implementing that behavior in your implementation of setSubtitle:.

Edit:

I see in comments that you are particularly concerned about point 3. The strings from [placemark locality] and [placemark administrativeArea] are passed as parameters to NSString's stringWithFormat method, after which they are irrelevant because their content has been copied into the new string that stringWithFormat returns. That is the only string you really have to worry about, and as has been pointed out setSubtitle: will retain that string.


Much has been written and said -- here and elsewhere -- about Cocoa memory management. Fundamentally, it's all an attempt to paraphrase or explain this: Memory Management Rules. Accept no substitutes. :-)


  1. Yes, you need to release geocoder in dealloc
  2. Yes, you are not responsible for releasing the NSString
  3. Yes, you are not responsible for releasing those NSStrings.

To obtain a better understanding of the memory management rules and standards, I would suggest reading the 'Memory Management Programming Guide' In particular, you may want to take some extra time to read the section 'Object Ownership and Disposal'.


Others have already addressed your main questions, but I'd like to point out a few other things:

  • It is conventional to assign the result of [super init] to self, like this:

    - init
    {
        self = [super init];
        if (!self) return nil;
    
        // do initialisation
    
        return self;
    }
    

    There are other, similar constructs that revolve around the value returned by [super init], but they always (by convention) involve assigning to self first.

  • Although unlikely to cause any problems in this case, it is generally more acceptable to avoid using accessor methods like setTitle: and setSubtitle: inside an initialiser method. The reason being that you may inadvertently trigger KVO notifications when your object is only in a partially-initialised state.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜