views:

105

answers:

3

Please see my comments in code:

-(id)initWithCoordinate:(CLLocationCoordinate2D)c title:(NSString *)t
{        
    [super init];
    coordinate = c;
    NSDate *today = [NSDate date];

    NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
    [dateFormatter setDateStyle:NSDateFormatterLongStyle];

    NSString* formattedDate = [NSString stringWithFormat:@"%@ %@",
                           [dateFormatter stringFromDate:today], t];


    [self setTitle:formattedDate]; //Why does the app crash when I try and release formattedDate?  I have after all passed its reference to the title property?


    [dateFormatter release]; //I need to release the dateformatter because I have finished using it and I have not passed on a reference to it

    return self;
}
+6  A: 

Nope, looks fine. stringWithFormat returns an autoreleased object - you don't own it unless you retain it, which you haven't, so you mustn't release it. You allocated dateFormatter yourself, so you do own it and must release.

(See the object ownership documentation and 8 squillion very similar SO questions. This must be the number one objective-c problem that crops up here by a significant margin.)

Edit: Actually, looking at your comment, there is a very slightly subtler issue here, though the upshot is the same (and actually underlines the point about ownership).

When you pass the string to setTitle, it could retain the string itself, in which case a call to release here might not cause a crash immediately. You would still be over-releasing, however, and it would bite you in the end. It just would be more difficult to locate the cause of the problem further down the line.

As it happens, setTitle makes a copy rather than retaining yours. This is pretty common with NSString properties. One reason is that you might pass an NSMutableString instead, and then randomly change it at some later point that might screw up the receiver. Taking a private copy is safer. As a bonus it exposes your over-releasing right away and allows you to fix it easily.

In any case, the point stands: only ever release something you know you own. If you've just passed it to some other object, it's that object's responsibility to handle whether it owns it or not, not yours.

walkytalky
+1 for link to Object Ownership docs.
chpwn
+1 for mentioning the previous 8 squillion questions.
JeremyP
A: 

You appear to have some radical misconceptions about how retain and release work. You say:

  1. "Why does the app crash when I try and release formattedDate? I have after all passed its reference to the title property"

  2. "I need to release the dateformatter because … I have not passed on a reference to it"

Whether you pass a reference to something is irrelevant to whether you're responsible for releasing it. The memory management rules dictate whether you should retain or release something, and they have practically nothing to do with passing references. You should read that document, because it's very fundamental and not really all that hard. Once you understand it, all your questions about this sort of thing will vanish.

The nutshell version is, you own an object and are responsible for releasing it if you obtained it from a new alloc or copy method or if you retained it. In the case of the NSDateFormatter, you got it from alloc, so you must release it. In the case of the string, none of those things are true, so you must not release this object that you don't own.

Chuck
A: 

Slightly unrelated, but...

Initializsers in ObjC are supposed to look like

- (id)init;
{
    self = [super init];
    if (self == nil)
        return self;
    ...
    return self;
}

This allows the super class to return a replacement. This is pretty advanced usage of ObjC, though, but it's a good habit to stick to this pattern.

More info at ADC: Allocating and Initializing Objects.

Daniel