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];

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?
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
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?
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
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?
[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
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?
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.
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.
Nice article !
For people who are interested I made a reusable singleton class on this blog:
http://www.devbypractice.com/reusable-singleton...