views:

1610

answers:

2

What's the best practice for retaining and releasing objects passed to class methods?

For instance, if you have a "class variable" declared like so:

static NSString *_myString = nil

...is the right thing to do this:

+ (void)myClassMethod:(NSString *)param {
    _myString = param;
}

... which has the drawback that the caller needs to maintain a nonzero retain count on param lest it be released prematurely. Alternatively one could do this:

+ (void)myClassMethod:(NSString *)param {
    [_myString autorelease];
    _myString = [param retain];
}

...which has the drawback that without a corresponding class-level dealloc call it will leak memory. Or should this sort of class variable chicanery be avoided completely, perhaps with a singleton class that manages the lifetime of these sorts of objects in a more conventional way?

Here are Apple's docs on creating a singleton instance:

http://developer.apple.com/documentation/Cocoa/Conceptual/CocoaFundamentals/CocoaObjects/CocoaObjects.html#//apple_ref/doc/uid/TP40002974-CH4-SW32

The code that I'm working with is the very slick (but still new) Objective Resource project (http://www.iphoneonrails.com/).

+1  A: 

Retain and release, absolutely. It's not a leak because the only time when a class's dealloc would be called is when the program ends — at which time the memory will be freed anyway. Doing it the first way would be more hassle and goes against the Cocoa memory-management guidelines.

As for whether it should be a class method or a singleton: Classes themselves generally should not have a lot of independent functionality. They just weren't designed that way in Objective-C, as you can see from the lack of class variables. Class methods should generally deal with creating and managing instances, and sometimes storing shared properties or defaults for all instances. The actual functionality of a class should go into instances. That's the convention in Objective-C.

(Of course, there is no Objective-C God and you're free to ignore conventions, but that's the general wisdom.)

Chuck
Classes don't have a dealloc method, only instances do.
dreamlax
Yeah, there's no dealloc for a class -- but it doesn't matter. Memory legitimately held by a global at program end isn't normally considered a leak (all singletons work like this).Definitely use a retain.
Matt Gallagher
I know classes don't have dealloc methods. That's what I meant: Even if classes did have such methods, they wouldn't ever be called.
Chuck
+2  A: 

Also, in the case of NSString or any class that has mutable variants (like NSArray or NSDictionary), I'd strongly recommend copying the parameter instead of retaining it. If the string the caller passed you was an NSMutableString, its value could change later, and it will change in your class as well. This is probably not what you want, so I'd advise doing this:

+ (void)myClassMethod:(NSString *)param {
    [_myString release];
    _myString = [param copy];
}

The copy method makes a copy and sets the retain count to 1, so you're all set as far as retaining the variable is concerned. And, as an extra bonus, if the caller does pass you an NSString, that class is smart enough to know that its value can't change, so it simply retains itself to avoid making a copy of the object. How clever is that?

Alex