views:

27

answers:

2

Instruments is pointing out that this is a memory leak, however I'm unsure how to release it properly, or when it should be released. Is there a better convention for assigning properties with new objects that are only needed inside a loop? The specific line is the "expense.addedDate = [NSDate new];".

- (void) addObjects:(NSString *)itemDescription withItemAmount:(NSString *)itemAmount {
// Add a new expense to the persistent store.
NSString *expenseDescription = itemDescription;
NSString *expenseAmount = itemAmount;
if (!expenseDescription.length || !expenseAmount.length) {
    UIAlertView *invalidEntry = [[[UIAlertView alloc] initWithTitle:@"Invalid Entry" 
                                                            message:@"You must include a description and cost." 
                                                           delegate:self 
                                                  cancelButtonTitle:@"OK" 
                                                  otherButtonTitles:nil] autorelease];
    [invalidEntry show];
} else {
    Expense *expense = (Expense *)[NSEntityDescription insertNewObjectForEntityForName:@"Expense"
                                                                inManagedObjectContext:self.managedObjectContext];
    expense.addedDate = [NSDate new];
    expense.itemDescription = expenseDescription;
    expense.cost = [NSNumber numberWithInt:[expenseAmount intValue]];

    NSError *error;
    if (![self.managedObjectContext save:&error]) {
        NSLog(@"Error %@", [error localizedDescription]);
        UIAlertView *errorSave = [[[UIAlertView alloc] initWithTitle:@"Unable to Save!" 
                                                            message:@"Money manager was not able to save this entry." 
                                                           delegate:self 
                                                  cancelButtonTitle:@"OK" 
                                                  otherButtonTitles:nil] autorelease];
        [errorSave show];
    } else {
        NSLog(@"Saved Expense to Database.");
    }
}

}

+1  A: 

I think you don't want to use the new selector, as it is not auto-released. If you're looking for a default, current timestamp, autoreleased NSDate object, you should use:

expense.addedDate = [NSDate date];

For the record,

[NSObject new]

is equivalent to

[[NSObject alloc] init]

Apple's docs on the new method

phooze
A: 

If you declare the property of "expense.addedDate" to use retain (@property(retain)) you should not assign the date as you do because the object will have a retainCount of 2, later when its freed it will cause a memleak.

Instead its sufficient to either use an autoreleased object or after assigning, release the object.

e.g.

expense.addedDate = [NSDate date];  // will return an autoreleased object

or

NSDate* dt = [NSDate new];
expense.addedDate = dt;
[dt release];

or a third way

NSDate* dt = [[NSDate new] autorelease];
Anders K.