views:

1332

answers:

3

I have a static method that creates an instance of the class and puts it in the static variable. I am wondering what the proper way of memory management is in this situation.

You can't put it in the dealloc-method, because although it can access the static variable any instance method that is created that get's released will also release the sharedInstance.

I guess there might be an option of creating a static destroy method which will manualy release the memory and can be called by the user from appWillTerminate, but that seems a bit odd.

So, again, the question: What is the proper way of releasing a static variable?


// MyClass.m
#import "MyClass.h"

static MyClass *myClass; // How to properly do memory management

@implementation MyClass

+ (MyClass *)sharedMyClass {
    if (myClass == nil) myClass = [[MyClass alloc] init];
    return myClass;
}
@end
+1  A: 

Just one of the reasons no-one likes singletons

You don't like singletons because you cannot properly free memory nanoseconds before the application terminates and all memory contents are discarded?
Kendall Helmstetter Gelner
try http://en.wikipedia.org/wiki/Global_variable
+3  A: 

You can either not release them, which is fine since the app is shutting down anyway. Cocoa on the iPhone already does this, it doesn't completely delete everything, it just lets the app get blown away.

Or you can delete it from appWillTerminate or some other shutdown function.

FigBug
Note that if you have a singleton one thing it might be a good idea to do is to have some kind of cleanup method, that can be called by the application delegate when it gets a low memory warning. You could even dump the whole static object at that time and let it be re-created if creation is not too expensive.
Kendall Helmstetter Gelner
A: 

You'll want to have a look at "Creating a Singleton" on the iPhone dev center to see how to properly implement that pattern. You won't be releasing your singleton, just letting it die when the application exits.

Also, if you're multithreaded you'll probably want to wrap that alloc in a @synchronize( self ) {}

Here is the full text:

Some classes of Foundation and the Application Kit create singleton objects. In a “strict” implementation, a singleton is the sole allowable instance of a class in the current process. But you can also have a more flexible singleton implementation in which a factory method always returns the same instance, but you can allocate and initialize additional instances.The NSFileManager class fits this latter pattern, whereas the UIApplication fits the former. When you ask for an instance of UIApplication, it passes you a reference to the sole instance, allocating and initializing it if it doesn’t yet exist.

A singleton object acts as a kind of control center, directing or coordinating the services of the class. Your class should generate a singleton instance rather than multiple instances when there is conceptually only one instance (as with, for example, NSWorkspace). You use singleton instances rather than factory methods or functions when it is conceivable that there might be multiple instances one day.

To create a singleton as the sole allowable instance of a class in the current process, you need to have an implementation similar to Listing 2-15. This code does the following:

Declare a static instance of your singleton object and initialize it to nil. In your class factory method for the class (named something like “sharedInstance” or “sharedManager”), generate an instance of the class but only if the static instance is nil. Override the allocWithZone: method to ensure that another instance is not allocated if someone tries to allocate and initialize an instance of your class directly instead of using the class factory method. Instead, just return the shared object. Implement the base protocol methods copyWithZone:, release, retain, retainCount, and autorelease to do the appropriate things to ensure singleton status. (The last four of these methods apply to memory-managed code, not to garbage-collected code.) Listing 2-15 Strict implementation of a singleton static MyGizmoClass

 *sharedGizmoManager = nil;  
 + (MyGizmoClass*)sharedManager {
     if (sharedGizmoManager == nil) {
         sharedGizmoManager = [[super allocWithZone:NULL] init];
     }
     return sharedGizmoManager; }  
 + (id)allocWithZone:(NSZone *)zone {
     return [[self sharedManager] retain]; }

 - (id)copyWithZone:(NSZone *)zone {
     return self; }

 - (id)retain {
     return self; }

 - (NSUInteger)retainCount {
     return NSUIntegerMax;  //denotes an object that cannot be released }

 - (void)release {
     //do nothing }

 - (id)autorelease {
     return self; }

If you want a singleton instance (created and controlled by the class factory method) but also have the ability to create other instances as needed through allocation and initialization, do not override allocWithZone: and the other methods following it as shown in Listing 2-15.

jessecurry