Is this the right way to do a singleton in Objective-C (coming from an Android background, with a little understanding of threading)?
#import "ItemsManager.h"
#define kNumMaxSelectableItems 15
@implementation ItemsManager{
NSMutableArray *currentItems;
}
static ItemsManager *myself;
-(id)init{
if(self=[super init]){
currentItems = [[NSMutableArray alloc] initWithCapacity:kNumMaxSelectableItems];
myself = self;
}
return self;
}
+(ItemsManager *)getInstance{
if(!myself){
myself = [[ItemsManager alloc] init];
}
return myself;
}
-(void) doSomething{
NSLog(@"hi");
}
-(void)dealloc{
[currentItems release];
currentItems = nil;
myself = nil;
[super dealloc];
}
@end
And with this design, I suppose I would call it like:
void main(){
[[ItemsManager getInstance] doSomething];
}
2 Answers 2
This is the the way singletons are usually implemented in apple's code samples.
+ (ItemsManager *)sharedInstance
{
static ItemsManager *sharedInstance = nil;
static dispatch_once_t once;
/* Doing the allocation inside dispatch_once queue ensures the code
will run only once for the lifetime of the app. */
dispatch_once(&once, ^{
sharedInstance = [[ItemsManager alloc] init];
});
return sharedInstance;
}
-
1\$\begingroup\$ I also would like to add a link to a Luke Redpath's post with a good explanation regarding using of this method: lukeredpath.co.uk/blog/a-note-on-objective-c-singletons.html \$\endgroup\$yas375– yas3752013年01月05日 22:25:20 +00:00Commented Jan 5, 2013 at 22:25
how do i hide the init method so that no one else can alloc/init my class without using "getInstance"?
there is not a widely accepted pattern how to do so.
In fact many (not only Objective-C) developer would argue today, that a classical strict Singleton is not needed and even harmful [1], [2], [3] — first of all Singletons make code hard to test, as the introduce global states and unit tests might yield different results if their order is changed.
Also Apple changed many real singleton in older Cocoa-Implementations to the softer shared instance pattern, in which actually many objects can be instantiated, but the class offers one shared one — and this is what dallen posted.
conclusion
Don't waste your time to try to make a bullet-proof singleton. It just don't worth the hassle. Use the approach dallen showed you and when it comes to unit testing be happy, that you can instantiate new objects.
that said: in the book "Objective-C Design Patterns for iOS", chapter 7, Carlo Chung shows an implementation of an Singleton, that is even sub-classable. But also in that chapter Chung points out the problems about singleton and advises to use the shared instance concept. Beware: that code predates ARC.
-
1\$\begingroup\$ Note though, that it's not necessary to add a public
init
to production code, just to allow it to be used for unit test. \$\endgroup\$Nate– Nate2013年05月24日 21:39:14 +00:00Commented May 24, 2013 at 21:39