-
-
Save haikusw/1050447 to your computer and use it in GitHub Desktop.
// Accessorizer's default generated singleton code for class Foo | |
static Foo *sharedInstance = nil; | |
+ (void) initialize | |
{ | |
if (sharedInstance == nil) | |
sharedInstance = [[self alloc] init]; | |
} | |
+ (id) sharedFoo | |
{ | |
//Already set by +initialize. | |
return sharedInstance; | |
} | |
+ (id) allocWithZone: (NSZone *) zone | |
{ | |
//Usually already set by +initialize. | |
@synchronized(self) | |
{ | |
if (sharedInstance) | |
{ | |
//The caller expects to receive a new object, so implicitly retain it | |
//to balance out the eventual release message. | |
return [sharedInstance retain]; | |
} else | |
{ | |
//When not already set, +initialize is our caller. | |
//It's creating the shared instance, let this go through. | |
return [super allocWithZone: zone]; | |
} | |
} | |
} | |
- (id) init | |
{ | |
//If sharedInstance is nil, +initialize is our caller, so initialize the instance. | |
//If it is not nil, simply return the instance without re-initializing it. | |
if (sharedInstance == nil) | |
{ | |
self = [super init]; | |
if (self) | |
{ | |
//Initialize the instance here. | |
} | |
} | |
return self; | |
} | |
- (id) copyWithZone: (NSZone *) zone | |
{ | |
return self; | |
} | |
- (id) retain | |
{ | |
return self; | |
} | |
- (unsigned) retainCount | |
{ | |
return UINT_MAX; // denotes an object that cannot be released | |
} | |
- (void) release | |
{ | |
// do nothing | |
} | |
- (id) autorelease | |
{ | |
return self; | |
} |
// Apple's documented version (from Cocoa Fundamentals Guide) | |
// http://developer.apple.com/library/ios/#documentation/Cocoa/Conceptual/CocoaFundamentals/CocoaObjects/CocoaObjects.html%23//apple_ref/doc/uid/TP40002974-CH4-SW32 | |
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; | |
} |
@quavera the two samples here https://gist.github.com/1050447#gistcomment-37789 and https://gist.github.com/1050447#gistcomment-37797 are really the best singleton implementations now (pre-blocks and post-blocks). I'd definitely encourage you to use them.
BTW: I had Apple's implementation in Accessorizer for several years. Then a bunch of developers chimed in saying it was not correct. This led to Peter's version. I see now he's changed it somewhat. But again, I'm going to release Accessorizer 3.0 in Aug/Sept with ARC support among other things. I'll add a updated version of a Singleton based on your input.
Thanks for those links!
editing the non blocks version to move static var out as both schwa and I generally do.
no more overrides? I got those overrides from Apple's documentation some time ago.
@quavera if you read the thread the consensus here seems to be:
- that the Apple docs aren't great
- it's not necessary to enforce singleton-ness
- less is better.
(I'm not 100% in agreement with #2, and will probably put an NSAssert into my - init that tests to see if the sharedInstance
is nil and assert if not. Something like NSAssert( sharedInstance == nil, @"initializing a second copy of your singleton class, probably not what you want");
either as an assert or a debug NSLog message.)
no more overrides.
they're dangerous and scramble the normal ref counting mechanism (which isn't even available to you in ARC anyway).
If the user wants to retain/release the singleton - let him. It won't cause any harm at all.
If the user decides to release it - well that's a stupid programmer who isn't following the Obj-C reference counting rules. Not much you can or should do to prevent that.
ARC makes all this noise go away.
thanks to all for this discussion - I have a few switches (options) in the Accessorizer Singleton code gen interface. I can re-implement/add some custom options there. People just need to email me what they want and I'll do my best to accommodate. Lastly, if there's ever a question with the code generated by Accessorizer, do NOT hesitate to contact me via email so we can discuss, modify, improve etc.
Fun addition: some Cocoa classes behave as "semi-singletons" on purpose. For example,
[NSFileManager defaultManager]
returns a "shared" file manager, but you can also (and apparently this is now the suggested method) use[[NSFileManager alloc] init]
and get a thread-safe one. (I can't think of any other examples right now...)