0

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.

3 Answers 3

3

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.

Sign up to request clarification or add additional context in comments.

16 Comments

but it is not a singleton — while close enough, IMO
@vikingosegundo why it is not?
Actually, it is a singleton. That it can be separately instantiated does not change that and there are a handful of Apple provided classes that do the same (NSFileManager comes to mind).
I would go with this definition: "A singleton pattern is a design pattern that restricts the instantiation of a class to one object." It is a sharedObject. That is close enough, but must be treated a bit different.
@bbum Actually NSFileManager WAS a Singleton (in CS terms): «The NSFileManger used to be a "strict" implementation of the Singleton pattern prior Mac OS X 10.5 and in iOS 2.0. […] Now creating new instances is recommended for thread-safty.» — Objective-C Design Patterns for iOS, pp 104. Apple uses the same definition, just to lie about NSFileManager and others in the very next chapter.
|
2

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.

Comments

1

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.]

1 Comment

I've been confused on how to work super keyword. I must have been out of my mind. Thank you.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.