Singleton classes are an important concept to understand because they exhibit an extremely useful design pattern. This idea is used throughout the iPhone SDK, for example, UIApplication has a method called sharedApplication which when called from anywhere will return the UIApplication instance which relates to the currently running application.

You can implement a singleton class in Objective-C using the following code:

MyManager.h

#import <foundation/Foundation.h>

@interface MyManager : NSObject {

}

+ (id)sharedManager;

@end

MyManager.m

#import "MyManager.h"

static MyManager *sharedMyManager = nil;

@implementation MyManager

#pragma mark Singleton Methods
+ (id)sharedManager {
	@synchronized(self) {
		if(sharedMyManager == nil)
			[[self alloc] init];
	}
	return sharedMyManager;
}
+ (id)allocWithZone:(NSZone *)zone {
	@synchronized(self) {
		if(sharedMyManager == nil)  {
			sharedMyManager = [super allocWithZone:zone];
			return sharedMyManager;
		}
	}
	return nil;
}
- (id)copyWithZone:(NSZone *)zone {
	return self;
}
- (id)retain {
	return self;
}
- (unsigned)retainCount {
	return UINT_MAX; //denotes an object that cannot be released
}
- (void)release {
	// never release
}
- (id)autorelease {
	return self;
}

Then you can reference the singleton from anywhere by calling the following function:

MyManager *sharedManager = [MyManager sharedManager];

I’ve used this extensively throughout my code for things such as creating a singleton to handle CoreLocation or CoreData functions.

Share and Enjoy:
  • Digg
  • del.icio.us
  • Facebook
  • Google Bookmarks
  • LinkedIn
  • Twitter

34 Responses to “Singleton Classes”

  1. Tommy says:

    Shouldn’t “static ExternalDataManager” be “static MyManager” ?

  2. Oops yes, thanks for spotting that! I’ve changed it now accordingly.

  3. mikew909 says:

    thanks a lot!! just what i was after , great work!

  4. Chris says:

    Is there anything to be aware of if I made a Singleton class like your example, but then subclassed it? e.g.

    #import
    #import “Singleton.h”

    @interface CodeDecodeUSStates : Singleton {

    }

    @end

    and then add any particular methods to the subclass to do various things. I assume those methods would be -(id) operation type? (as opposed to the class side + ).

    and, should I worry about this warning when I tried this:

    CodeDecodeUSStates *p = [CodeDecodeUSStates sharedInstance]; // Used sharedInstance instead of sharedManager

    tia

  5. Chris says:

    Oops, the warning I get (build time) is
    initialization from distinctive Objective-C type
    on the assignment

  6. Hi Chris,

    That warning will be because you need to do:
    CodeDecodeUSStates *p = (CodeDecodeUSStates*)[CodeDecodeUSStates sharedInstance];

    That’s just because sharedInstance returns id, rather than CodeDecodeUSStates. You can ignore the warning, but it’s probably best to cast anyway as it’s better practice to do that.

    As for subclassing, that’s fine and you can add instance or class methods to the subclass and they will work just fine.

    Thanks for reading my tutorial!

  7. Corbin says:

    I’m new to Objective-C. How would I go about storing various variables into this, so I could access them in other views.

    Example of PHP:
    global $fruit;
    $fruit = ‘apples’;

    Instinctively I would try (but this doesn’t work):
    #import MyManager.h
    [MyManager *sharedManager = [MyManager sharedManager]
    [sharedManager.fruit retain:@"apples"]

  8. Hi Corbin,

    If you wanted to do what you’re trying, then you would add a property to MyManager called fruit (probably an NSString) and then you could do:

    MyManager *sharedManager = [MyManager sharedManager];
    sharedManager.fruit = @"apples";

    That would then set the fruit property to ‘apples’.

    If you’re wondering how to add a fruit property:

    #import <Foundation/Foundation.h>
     
    @interface MyManager : NSObject {
       NSString *fruit;
    }
     
    @property (nonatomic, retain) NSString *fruit;
     
    + (id)sharedManager;
     
    @end

    And then @synthesize it in the MyManager.m.

    Does that help at all?

  9. iPhone2020 says:

    Good post Matt. In the above post you showed to define fruit property which is of type NSString. I want to use a NSInteger in my code. When i use it in similar way it gives me an error “property “my variable name” with retain attribute must be of object type.

    I also would like to know how to define these variables with some value in singleton class. For example
    You showed to define fruit in MyManager above, is there a way to set some value to it
    fruit = Mango

    and then change it using
    MyManager *sharedManager = [MyManager sharedManager];
    sharedManager.fruit = @”apples”;

    Thanks

  10. admin says:

    NSInteger is a typedef to int so it’s not an object type. For that reason you would do:

    @property (nonatomic) NSInteger integerValue;

    i.e. not a pointer and not retain on the property.

    Also, if you wanted to set the default of `fruit’ to be `mango’ then you’d just set it to be so in the init method.

  11. Jeff says:

    Thank you very much for posting this. I’m new to Objective-C and I know of the design pattern, but the implementation was hanging me up. I want a singleton to control the access to the application save data file that I will use to return the user to where they left off if a call should interrupt the application.

  12. Rob says:

    Unfortunately the method for casting a subclassed singleton to the child class doesn’t work for me.

    Here is my code:

    NSLog([(GameModel *)[GameModel instance] status]);

    The ‘GameModel’ singelton subclasses the ‘Singleton’ singleton. I get an error as soon as I try to call the instance method ’status’ on GameModel, even though I am casting the returned id to GameModel. A method on the parent class works fine.

    “*** Terminating app due to uncaught exception ‘NSInvalidArgumentException’, reason: ‘*** -[Singleton status]: unrecognized selector sent to instance 0×44627d0′”

  13. Rob,

    Umm that’s sort of fair enough though. Using my way of doing singletons you cannot subclass them unfortunately. That’s because your base Singleton class will have create a static which cannot be shared between the various subclasses.

    You’ll need to copy the singleton code for each subclass you want to create unfortunately.

  14. Rob says:

    Thanks for your quick reply Matt.

    Yes it looks like Singletons are not subclassable in Obj-C which is a pity, since I often use that design pattern to create project-specific versions of managers (or even a projects MVC model which subclasses a generic model).

    I’ve found a half way solution if I don’t want to actually instantiate singletons higher up the inheritance chain. I only reproduce the 2 static methods and the static variable in the lowest class. I can then inherit other methods from all the way up the chain.

  15. Hi Rob,

    Using inheritance on a singleton really doesn’t make sense. If you really want the ease of coding where you don’t want to keep typing / copy&pasting the singleton methods then you could put all the singleton methods into a #define and use that. You could do something along the lines of:

    #define make_singleton ( x ) \
    static MyManager *shared##x = nil; \
    + (id)sharedManager { \
    	@synchronized(self) { \
    		if(shared##x == nil) \
    			[[self alloc] init]; \
    	} \
    	return shared##x; \
    }

    …and then do something like:

    @implementation DataManager
    make_singleton (DataManager)
    @end

    (I haven’t tested that by the way!)

    That might be easier for you?

  16. MattMac says:

    Hi I have followed the code above for my own app. I have declared the sharedManager in one of my view controllers which is correct. I have tried to access the variable in a different controller however the NSLog is showing the value to read

    MyManager *sharedManager = [MyManager sharedManager];
    NSLog(@”test%@”, sharedManager);

    Where am I going wrong?

  17. Hi MattMac,

    What is it showing in another view? It really should work if you’ve followed my guide. The value from that NSLog line should show the same when called from any view. It should show a MyManager which has the same memory address no matter where you call it from.

    Can you elaborate on your problem some more?

  18. Jake says:

    Hi
    I am trying to set a NSString in the singleton to be a text fields text. The code I am using is

    MyManager *sharedManager = [MyManager sharedManager];
    sharedManager.theString = textField.text;

    I am trying to set a label in a different view controller to this text by using this code:

    MyManager *sharedManager = [MyManager sharedManager];
    shower.text = sharedManager.theString;

    I have set up an NSLog to log the text of sharedManager.theString, but everytime it returns NULL. How can I fix this?

  19. @Jake Hmm that is odd. Is the label being set after the string is set? Also, try setting theString to a default value in the MyManager initialiser. Also, try logging theString after setting it to the textField.text value to see if it made it in OK (i.e. the property is set up OK on MyManager).

  20. Jake says:

    what method should i set the initial value in? when i put it in

    + (id)sharedManager {

    or

    + (id)allocWithZone:(NSZone *)zone {

    i get a warning

  21. @Jake – To set the initial value you should create an init function like so:

    - (id)init {
        if(self = [super init]) {
            theString = @"Default Value";
        }
        return self;
    }

    You can’t set in sharedManager or allocWithZone as they are class methods (+) rather than instance methods (-) so they have no idea what self.theString is.

  22. Jake says:

    im using this code

    -(id)init {
    if(self = [super init]) {
    theString = @”hello”;
    }
    return self;
    }

    in MyManager and in the view controller i am using:

    Singleton *sharedManager = [Singleton sharedManager];
    NSLog(@”%@”, sharedManager.theString)

    and every time it returns NULL!!!! wat am i donig wrong???!!!!!

  23. @Jake – If you’d like, send me the XCode project to matt at galloway dot me dot uk and I’ll try to solve it for you.

  24. Joe Schorn says:

    Thanks a bunch. This came in very helpful in a project I’m currently working on.

  25. Matt Guest says:

    Hi everyone, I have found this guide very useful. However I have a small problem.

    I added a property in the fruit example above to MyManager and I can access that as I wish from other classes. However, in the exact same way I added a 2nd property and I get a ‘error: request for member in something not a structure or union’ error on compiling.

    Hmmm, I thought, perhaps you can only use one property in the MyManager class. As a test I replaced the code from the first property with the property of the second. Exactly the same problem. I fear I am missing something elementary out, but can anyone think what the issue may be? I’ve been on this all day.

    Many Thanks in advance
    Matt

  26. Matt Guest says:

    Furthermore to the problem above I have realised that the property is passed successfully to one viewcontroller class, but not to another. Both classes have identical code for retrieving the properties value and have imported the MyManager.h. One returns correctly and the other returns null…

    View 1 doesnt retrieve the property, view 2 does.
    The property is set to MyManager in the RootViewController, which pushes View 1. View 2 is pushed by View 1.

    I think I’m clearly making a big mistake somewhere and my head is fried!!

  27. @Matt – if you send over your code then I can take a look for you if you like? You could either send the whole project folder, or just the MyManager.(h/m).

  28. Ty says:

    Quick question: How do you release the single alloced instance?

  29. @Ty put simply, you don’t. And that’s the point about the Singleton class idea. You don’t need tonrelease it. You could if you want to put in a method on the class to reset it where you release the static variable and then set the static to nil.

  30. Ty says:

    Yes, I understand. Let it get handled when the app closes.

  31. Florian Wagner says:

    Hey folks! I used exactly the same singleton pattern as statet above and got an NSString ( NSString *dbPath; ) and an NSInteger test;
    with

    @property (nonatomic, retain) NSString *dbPath;
    @property (nonatomic, readwrite) NSInteger test;

    The String should keep my database path. Running the dbPath function and setting it with self.dbPath and the self.test works fine but when I access the singleton class from a view controller my set integer value is present but the NSString seems to have already been released => It shows an “Out of scope”

    Any suggestions? Do you need more information? Anybody with the same error? The thing is I am using EXACTLY the same SingletonClass in another application and the string and integer values are stored and accessable without any problems…

  32. @Florian – The NSString is an object, the NSInteger isn’t – it’s an int. This might be why you’re seeing the difference. It does seem odd though that it’s working in one app and not the other :-S. Could you share any more code with us at all?

    One thing I’d suggest is to check that you’re not releasing the NSString too many times. Perhaps even change that property to (nonatomic, copy) to make it copy the value you set rather than retaining the one you pass in.

  33. Thanks so far Matt,
    I am actually at an exebition far away from my MAC but I can share some more code when I come back in 10 days.
    I have actually outcommened with // any release of the strings and the object for it is a singlton can never be released, right…
    It’s so strange. I also changed the properties as you recomended but they still disappear.
    Have any suggestions at which point the NSString object might be autoreleased by the singlton pattern found on apples developer website???

  34. @Florian – Make sure that when you set the string, you’re retaining it in the singleton. You can either have the property set to assign or copy to achieve this but I usually use copy for NSStrings.

    So one of these 2:

    @property (nonatomic, retain) NSString *myString;
    @property (nonatomic, copy) NSString *myString;

    Then you would make sure to @synthesize them in the implementation and use the setter method:

    mySingleton.myString = @"Some string";
    [mySingleton setMyString:@"Some string"];

    Does that help?

Leave a Reply