Reputation: 1105
I'm playing around with idea of singleton cache. The setup is quite simple:
In my singleton class, I am instantiating one instance as follows:
+(SharedInstanceTest*)sharedInstace
{
static SharedInstanceTest *sharedInstace=nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedInstace=[[SharedInstanceTest alloc]init];
});
NSLog(@"Share Instance Allocated");
return sharedInstace;
}
+(id)allocWithZone:(NSZone *)zone
{
return [self sharedInstace];
}
Now in the rootViewController, I am calling the sharedInstance just so that I can see the NSLog to make sure it has been instantiated.
-(void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
[SharedInstanceTest sharedInstace];
}
I get no NSLog. Any idea why?
Upvotes: 0
Views: 82
Reputation: 64022
You can override allocWithZone:
in order to prevent clients from creating more instances. You just can't use alloc
to create the shared instance, because that will end up calling allocWithZone:
; then you have an infinite loop, as SB. answered.
You can do something like this (to convert to ARC, just remove the retain
in allocWithZone:
):
#import "MySingleton.h"
static MySingleton * defaultMySingleton = nil;
//MySingleton * defaultMySingleton = nil;
//void initialize_defaultMySingleton(void) {
// [MySingleton defaultMySingleton];
//}
@implementation MySingleton
+ (MySingleton *)defaultMySingleton {
// Create the instance if it has not been already.
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
// Call super's implementation because allocWithZone: is overridden
// to call defaultMySingleton
// The class owns this instance.
defaultMySingleton = [[super allocWithZone:NULL] init];
});
return defaultMySingleton;
}
+ (id)allocWithZone:(NSZone *)zone {
// Users of alloc, although they shouldn't be using this,
// will expect a +1 retain count. Bump it to allow for eventual release.
return [[self defaultMySingleton] retain];
}
- (id)init
{
// If defaultMySingleton exists, then it is self here. Just return it.
if( defaultMySingleton ) return defaultMySingleton;
// Otherwise, do normal setup.
self = [super init];
if( !self ) return nil;
return self;
}
@end
This was inspired by Peter Hosey's singleton blog post, though he seems to have changed his implementation quite a bit since I last read it.
Upvotes: 0
Reputation: 22914
Do not override allocWithZone
. It is probably causing a loop or something when you do [SharedInstanceTest alloc]
.
Upvotes: 2