The Objective-C Singleton

August 30th, 2009 by Derek van Vliet Leave a reply »

One of the most useful patterns that we have employed in our iPhone game is the singleton. For those who don’t know, singletons are a class that only gets instantiated once in your application’s run-time. They often take the form of manager or factory classes. A good example of a singleton is the web-based resource manager class that we posted about recently.

We have been using singletons for a variety of things in our cocos2d-based game. Including:

  • Resource management
  • Atlas sprite managers
  • User settings management
  • Score management

Below is a template for the singletons that we use in objective-c.

MySingleton.h:

#import <Foundation/Foundation.h>
 
@interface MySingleton : NSObject {
 
}
+(MySingleton*)sharedMySingleton;
-(void)sayHello;
@end

MySingleton.m:

@implementation MySingleton
static MySingleton* _sharedMySingleton = nil;
 
+(MySingleton*)sharedMySingleton
{
	@synchronized([MySingleton class])
	{
		if (!_sharedMySingleton)
			[[self alloc] init];
 
		return _sharedMySingleton;
	}
 
	return nil;
}
 
+(id)alloc
{
	@synchronized([MySingleton class])
	{
		NSAssert(_sharedMySingleton == nil, @"Attempted to allocate a second instance of a singleton.");
		_sharedMySingleton = [super alloc];
		return _sharedMySingleton;
	}
 
	return nil;
}
 
-(id)init {
	self = [super init];
	if (self != nil) {
		// initialize stuff here
	}
 
	return self;
}
 
-(void)sayHello {
	NSLog(@"Hello World!");
}
@end

Example Usage

Using the methods of the singleton is then as easy as this:

[[MySingleton sharedMySingleton] sayHello];

  • Jey350
    Nice article !
    For people who are interested I made a reusable singleton class on this blog:
    http://www.devbypractice.com/reusable-singleton...
  • Petrus Ali Saputra
    Hi, I've tried this code. But I got "error: 'VariableStore' undeclared (first use in this function)" message when trying to use it. Anything wrong? Plz help.

    I rename MySingleton to VariableStore. Thanks.
  • Where do you instantiate this from? I tried from inside viewDidLoad on a UIView, and was told in an IBAction method further up that the instance was undeclared...

    Where do you instantiate to ensure all methods can access it?
  • Fireball
    Thanks for the tutorial. Works perfectly. I'm new to ObjC programming for iphone.

    i tried to have a NSArray instead of NSString except i dont know the syntax for accessing it.

    [[MySingleton sharedMySingleton] [myArray arrayWithObjects: @"test", nil]];

    How do i achieve this?
  • Fireball
    [MySingleton sharedMySingleton].QQQ = [NSArray arrayWithObjects: @"test", nil];
    I think this is the correct syntax.

    How do I do something like [MySingleton sharedMySingleton] [QQQ objectAtIndex:0]; ?

    thanks in advance
  • duponol
    Dear,

    Thanks for the tutorial, I think I got it working however, the singleton itself works ok I think but now i want to share a simple NSString in it. I want to be able to set it and get it.

    header file:
    Code:

    #import <Foundation/Foundation.h>
    @interface Global : NSObject {
    NSString *test;
    }

    @property (nonatomic, retain) NSString* test;

    +(Global*)sharedMySingleton;
    -(void)sayHello;
    @end

    implementation:
    Code:

    #import "Global.h"

    @implementation Global

    @synthesize test;

    static Global* _sharedMySingleton = nil;

    +(Global*)sharedMySingleton
    {
    @synchronized([Global class])
    {
    if (!_sharedMySingleton) {
    [[self alloc] init];
    }

    return _sharedMySingleton;
    }

    return nil;
    }

    +(id)alloc
    {
    @synchronized([Global class])
    {
    NSAssert(_sharedMySingleton == nil, @"Attempted to allocate a second instance of a singleton.");
    _sharedMySingleton = [super alloc];
    return _sharedMySingleton;
    }

    return nil;
    }

    -(id)init {
    self = [super init];
    if (self != nil) {
    // initialize stuff here
    }
    return self;
    }

    -(void)sayHello {
    NSLog(@"test has value: %@",self.test);
    }

    @end

    This works from an other class where I try to access the singleton:
    Code:

    [Global sharedMySingleton].test = @"first assignment";
    [[Global sharedMySingleton] sayHello];

    But when I try the next thing then my application terminates:
    Code:

    NSLog("singleton: %@",[Global sharedMySingleton].test);

    I also get the warning: warning: passing argument 1 of 'NSLog' from incompatible pointer type

    Any help is highly appriciated, I think i'm missing something coceptually.
  • duponol, when I copied your code into xcode it worked as expected. I see the following output in the console:

    test has value: first assignment

    Are you writing an iPhone app or another type of mac app?
  • duponol
    Hey Derek,

    I'm embaressed to say it but I found my error, it was the second piece of code that diden't work:

    NSLog("singleton: %@",[Global sharedMySingleton].test);

    There is no @ in front of the "singleton: %@", I was so hang up in the singleton that I wasn't seeing clear. Sorry for your trouble and thanks for the reply and the tutorial.

    Kind regards,
    Olivier
blog comments powered by Disqus