Live2Enjoy7
Live2Enjoy7

Reputation: 1105

Singleton Not Instantiating Correctly

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

Answers (2)

jscs
jscs

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

NG.
NG.

Reputation: 22914

Do not override allocWithZone. It is probably causing a loop or something when you do [SharedInstanceTest alloc].

Upvotes: 2

Related Questions