R – Should I send retain or autorelease before returning objects

cocoa-touchiphonememory-managementobjective c

I thought I was doing the right thing here but I get several warnings from the Build and Analyze so now I'm not so sure. My assumption is (a) that an object I get from a function (dateFromComponents: in this case) is already set for autorelease and (b) that what I return from a function should be set for autorelease. Therefore I don't need to send autorelease or retain to the result of the dateFromComponents: before I return it to the caller. Is that right?

As a side note, if I rename my function from newTimeFromDate: to gnuTimeFromDate the analyzer does not give any warnings on this function. Is it the convention that all "new*" methods return a retained rather than autoreleased object?

In Memory Management Programming Guide for Cocoa it says "A received object is normally guaranteed to remain valid within the method it was received" and that "That method may also safely return the object to its invoker." Which leads me to believe my code is correct.

However, in Memory Management in Cocoa it says "Assume that objects obtained by any other method have a retain count of 1 and reside in the autorelease pool. If you want to keep it beyond the current scope of execution, then you must retain it." Which leads me to think I need to do a retain before returning the NSDate object.

I'm developing with Xcode 3.2.1 on 10.6.2 targeting the iPhone SDK 3.1.2.

screenshot of build/analyze output http://nextsprinter.mggm.net/Screen%20shot%202009-11-15%20at%2008.33.00.png

Here's the code in case you have trouble reading the screen shot:

//============================================================================
// Given a date/time, returns NSDate for the specified time on that same day
//============================================================================
+(NSDate*) newTimeFromDate:(NSDate*)fromDate 
       Hour:(NSInteger)hour 
     Minute:(NSInteger)min 
     Second:(NSInteger)sec
{
 NSCalendar* curCalendar = [NSCalendar currentCalendar];
 const unsigned units    = NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit;
 NSDateComponents* comps = [curCalendar components:units fromDate:fromDate];
 [comps setHour:   hour];
 [comps setMinute: min];
 [comps setSecond: sec];

 return [curCalendar dateFromComponents:comps];
}

Best Answer

You are nearly right. The only problem that clang correctly points out is that your method promises a retain count +1 object (for its name containing “new”) but you are returning an autoreleased object.

You have two options: removing the “new" from the method name or retaining the returned object. It’s far more Cocoa-ish to return the autoreleased object (as you do) and name the method timeFromDate:.

Related Topic