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
- As I created the geocoder object via the
alloc
method, I have to release it (done indealloc
). Correct? - In method
reverseGeocoder:didFindPlacemark
a NSString is created with the convenience methodstringWithFormat
. As I didn't usealloc
, I'm not responsible for releasing that (I assume that method usesautorelease
). Is that right? - The object
placemark
returns two NSStrings,locality
andadministrativeArea
. 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 withautorelease
. The propertysubtitle
is declared withretain
. 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.
- 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.
- 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.
- 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 ofsetSubtitle:
.
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. :-)
- Yes, you need to release geocoder in dealloc
- Yes, you are not responsible for releasing the NSString
- 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]
toself
, 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 toself
first.Although unlikely to cause any problems in this case, it is generally more acceptable to avoid using accessor methods like
setTitle:
andsetSubtitle:
inside an initialiser method. The reason being that you may inadvertently trigger KVO notifications when your object is only in a partially-initialised state.
精彩评论