简体   繁体   中英

Singleton in Objective C (Non-ARC)

I have found how to implement singleton in objective c (Non-ARC).

Matt Galloway's singleton

// AppTools.h in my code

@interface AppTools : NSObject {

    NSString *className;
}

@property ( nonatomic, retain ) NSString *className;

+ ( id ) sharedInstance;

@end    // AppTools


// AppTools.m in my code

static AppTools *sharedAppToolsInstance = nil;

@implementation AppTools

@synthesize className;

- ( id ) init {

    self = [ super init ];
    if ( self ) {
        className = [ [ NSString alloc ] initWithString: @"AppTools" ];
    }
    return self;
}   // init

- ( void ) dealloc {

   // Should never be called, but just here for clarity really.
   [ className release ];
   [ super dealloc ];
}   // dealloc

+ ( id ) sharedInstance {

    @synchronized( self ) {
    if ( sharedAppToolsInstance == nil )
        sharedAppToolsInstance = [ [ super allocWithZone: NULL ] init ];
    }
    return sharedAppToolsInstance;
}   // sharedInstance

+ ( id ) allocWithZone: ( NSZone * )zone {

    return [ [ self sharedInstance ] retain ];
}   // allocWithZone:

- ( id ) copyWithZone: ( NSZone * )zone {

    return self;
}   // copyWithZone:

- ( id ) retain {

    return self;
}   // retain

- ( unsigned int ) retainCount {

    return UINT_MAX;    // denotes an object that cannot be released
}   // retainCount

- ( oneway void ) release {

    // never release
}   // release

- ( id ) autorelease {

    return self;
}   // autorelease

I'd like to know how to work allocWithZone: in sharedInstance method. On this, the allocWithZone: method's receiver is 'super' and 'super' is NSObject. Though return value is NSObject instance, it is substituted to sharedInstance.

Where is className's memory room then? I don't know how to work this part of the code.

Thank in advance.

I think that code that you have posted is too difficult to use for creating singletons.

In all my project I am using the following code to use singletons. It is very simple, thread-safe and works perfectly:

+ (CustomClass *)shared
{
    static CustomClass *singleton = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        singleton = [[CustomClass alloc] init];
    });
    return singleton;
}

And I believe you could use it in ARC and non-ARC projects.

UPDATE: As mentioned in comments it is actually shared object and not singleton because there could be created more the one instance of particular class. But it is close enough.

In my opinion, if you are not writing open source code/libraries and nobody else will use it then it might be much easier to use shared objects and treat them as singletons.

I use the same code as Nekto but singleton = [[CustomClass alloc] init]; should be singleton = [[self alloc] init]; .

Imagine a subclass CustomSubclass . If you call

CustomSubclass *sharedObject = [CustomSubclass shared];

you will not get a CustomSubclass but a CustomClass .

You ask "Where is className's memory room then?"

Most classes do not implement alloc or allocWithZone themselves but rely on the implementation inherited from NSObject . The NSObject implementation allocates an object of the original calling class .

So in your example AppTools does override allocWithZone , this implementation invokes NSObject 's allocWithZone via a call to super , and NSObject 's method performs the actual allocation and returns an object of type AppTools .

[Note: If you are wondering how NSObject 's implementation knows what kind of object to allocate then this is simple - calling an inherited method does not alter the self argument to the method, alloc / allocWithZone are class methods, and the self argument of a class method references the class object (rather than an instance object of the class) itself.]

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM