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.]
Related
I'm trying to understand the Singleton concept in objective-c.
Most examples that I did found just refer to a single variable.
I'm a bit lost about how to adapt the examples to handle many variables as per an example the accelerometer values that return x, y, z.
Can you guide me a bit further ?
A Singleton refers to a special object that can only exist once inside the lifespan of your application. That object can have as many variables and properties as necessary.
// Singleton.h
#interface Singleton : NSObject
#property (readwrite) int propertyA;
#property (readwrite) int propertyB;
#property (readwrite) int propertyC;
+ (Singleton *)sharedInstance;
#end
The key to a Singleton is that it can only be created once. Usually in Objective-C we use the #synchronized() directive to make sure it only gets created once. We put this in a convenience class method called sharedInstance and return our Singleton. Since the Singleton is just an object it can easily have multiple properties, variables, and methods.
// Singleton.m
#import "Singleton.h"
#interface Singleton ()
{
int variableA;
int variableB;
int variableC;
}
#end
#implementation Singleton
static Singleton *sharedInstance = nil;
+ (Singleton *)sharedInstance
{
#synchronized(self) {
if (sharedInstance == nil) {
sharedInstance = [[Singleton alloc] init];
}
}
return sharedInstance;
}
+ (id)allocWithZone:(NSZone *)zone {
#synchronized(self) {
if (sharedInstance == nil) {
sharedInstance = [super allocWithZone:zone];
return sharedInstance;
}
}
return nil;
}
- (id)init {
self = [super init];
if (self) {
// Inits
}
return self;
}
#end
This is not the ONLY way to create a Singleton. Remember the important part is it can only be created once. So you can take advantage of newer Grand Central Dispatch calls when developing for OSX and iOS such as dispatch_once.
Talking to the Singleton
So lets say you have another object elsewhere talking to the Singleton. This can be done anywhere you #import "Singleton.h"
- (void)someMethod
{
// Setting properties
int valueA = 5;
[[Singleton sharedInstance] setPropertyA:valueA];
// Reading properties
int valueB = [[Singleton sharedInstance] propertyB];
}
How do I convert (or create) a singleton class that compiles and behaves correctly when using automatic reference counting (ARC) in Xcode 4.2?
In exactly the same way that you (should) have been doing it already:
+ (instancetype)sharedInstance
{
static MyClass *sharedInstance = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedInstance = [[MyClass alloc] init];
// Do any other initialisation stuff here
});
return sharedInstance;
}
if you want to create other instance as needed.do this:
+ (MyClass *)sharedInstance
{
static MyClass *sharedInstance = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedInstance = [[MyClass alloc] init];
// Do any other initialisation stuff here
});
return sharedInstance;
}
else,you should do this:
+ (id)allocWithZone:(NSZone *)zone
{
static MyClass *sharedInstance = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedInstance = [super allocWithZone:zone];
});
return sharedInstance;
}
This is a version for ARC and non-ARC
How To use:
MySingletonClass.h
#interface MySingletonClass : NSObject
+(MySingletonClass *)sharedInstance;
#end
MySingletonClass.m
#import "MySingletonClass.h"
#import "SynthesizeSingleton.h"
#implementation MySingletonClass
SYNTHESIZE_SINGLETON_FOR_CLASS(MySingletonClass)
#end
This is my pattern under ARC.
Satisfies new pattern using GCD and also satisfies Apple's old instantiation prevention pattern.
#implementation AAA
+ (id)alloc
{
return [self allocWithZone:nil];
}
+ (id)allocWithZone:(NSZone *)zone
{
[self doesNotRecognizeSelector:_cmd];
abort();
}
+ (instancetype)theController
{
static AAA* c1 = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^
{
c1 = [[super allocWithZone:nil] init];
// For confirm...
NSLog(#"%#", NSStringFromClass([c1 class])); // Prints AAA
NSLog(#"%#", #([c1 class] == self)); // Prints 1
Class real_superclass_obj = class_getSuperclass(self);
NSLog(#"%#", #(real_superclass_obj == self)); // Prints 0
});
return c1;
}
#end
Read this answer and then go and read the other answer.
You must first know what does a Singleton mean and what are its requirements, if you don't understand it, than you won't understand the solution--at all!
To create a Singleton successfully you must be able to do the following 3:
If there was a race condition, then we must not allow multiple instances of your SharedInstance to be created at the same time!
Remember and keep the value among multiple invocations.
Create it only once. By controlling the entry point.
dispatch_once_t helps you to solve a race condition by only allowing its block to be dispatched once.
Static helps you to “remember” its value across any number of
invocations. How does it remember? It doesn't allow any new instance with that exact name of your sharedInstance to be created again it just works with the one that was created originally.
Not using calling alloc init (i.e. we still have alloc init methods since we are an NSObject subclass, though we should NOT use them) on our sharedInstance class, we achieve this by using +(instancetype)sharedInstance, which is bounded to only be initiated once, regardless of multiple attempts from different threads at the same time and remember its value.
Some of the most common system Singletons that come with Cocoa itself are:
[UIApplication sharedApplication]
[NSUserDefaults standardUserDefaults]
[NSFileManager defaultManager]
[NSBundle mainBundle]
[NSOperations mainQueue]
[NSNotificationCenter defaultCenter]
Basically anything that would need to have centralized effect would need to follow some sort of a Singleton design pattern.
Alternatively, Objective-C provides the +(void)initialize method for NSObject and all its sub-classes. It is always called before any methods of the class.
I set a breakpoint in one once in iOS 6 and dispatch_once appeared in the stack frames.
Singleton Class : No one can create more than one object of class in any case or through any way.
+ (instancetype)sharedInstance
{
static ClassName *sharedInstance = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedInstance = [[ClassName alloc] init];
// Perform other initialisation...
});
return sharedInstance;
}
// You need need to override init method as well, because developer can call [[MyClass alloc]init] method also. that time also we have to return sharedInstance only.
-(MyClass)init
{
return [ClassName sharedInstance];
}
There are two issues with the accepted answer, which may or may not be relevant for your purpose.
If from the init method, somehow the sharedInstance method is called again (e.g. because other objects are constructed from there which use the singleton) it will cause a stack overflow.
For class hierarchies there is only one singleton (namely: the first class in the hierarchy on which the sharedInstance method was called), instead of one singleton per concrete class in the hierarchy.
The following code takes care of both of these problems:
+ (instancetype)sharedInstance {
static id mutex = nil;
static NSMutableDictionary *instances = nil;
//Initialize the mutex and instances dictionary in a thread safe manner
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
mutex = [NSObject new];
instances = [NSMutableDictionary new];
});
id instance = nil;
//Now synchronize on the mutex
//Note: do not synchronize on self, since self may differ depending on which class this method is called on
#synchronized(mutex) {
id <NSCopying> key = (id <NSCopying>)self;
instance = instances[key];
if (instance == nil) {
//Break allocation and initialization into two statements to prevent a stack overflow, if init somehow calls the sharedInstance method
id allocatedInstance = [self alloc];
//Store the instance into the dictionary, one per concrete class (class acts as key for the dictionary)
//Do this right after allocation to avoid the stackoverflow problem
if (allocatedInstance != nil) {
instances[key] = allocatedInstance;
}
instance = [allocatedInstance init];
//Following code may be overly cautious
if (instance != allocatedInstance) {
//Somehow the init method did not return the same instance as the alloc method
if (instance == nil) {
//If init returns nil: immediately remove the instance again
[instances removeObjectForKey:key];
} else {
//Else: put the instance in the dictionary instead of the allocatedInstance
instances[key] = instance;
}
}
}
}
return instance;
}
#import <Foundation/Foundation.h>
#interface SingleTon : NSObject
#property (nonatomic,strong) NSString *name;
+(SingleTon *) theSingleTon;
#end
#import "SingleTon.h"
#implementation SingleTon
+(SingleTon *) theSingleTon{
static SingleTon *theSingleTon = nil;
if (!theSingleTon) {
theSingleTon = [[super allocWithZone:nil] init
];
}
return theSingleTon;
}
+(id)allocWithZone:(struct _NSZone *)zone{
return [self theSingleTon];
}
-(id)init{
self = [super init];
if (self) {
// Set Variables
_name = #"Kiran";
}
return self;
}
#end
Hope above code will help it out.
if you need to create singleton in swift,
class var sharedInstance: MyClass {
struct Singleton {
static let instance = MyClass()
}
return Singleton.instance
}
or
struct Singleton {
static let sharedInstance = MyClass()
}
class var sharedInstance: MyClass {
return Singleton.sharedInstance
}
you can use this way
let sharedClass = LibraryAPI.sharedInstance
I know that the whole point of singleton is to instantiate 1 instance of the onject and reuse it, but when it comes to unit testing I want to be able to renew the singleton object before every test.
I tried to use a category to access the singleton object and release it but It's not accessible by categories any idea what's the best way to achieve this?
#implementation SingletonClass
static SingletonClass *singleton;
+ (SingletonClass*)sharedInstance
{
if (!singleton)
{
singleton = [[SingletonClass alloc] init];
}
return singleton;
}
#end
.
#implementation SingletonClass(Unit Testing Additions)
+ (void)killInstance
{
// I get an error here and I cannot access the singleton Object
[singleton release], singleton = nil;
}
#end
By the very definition of singleton, you can't do this.
If it is your class, don't make it a singleton.
If it isn't your class, doing this will fail.
I'm not sure whether this will work, but maybe you could just override the sharedInstance class method and manage the singleton yourself:
#implementation SingletonClass (Unit Testing Additions)
static SingletonClass *myVeryOwnSharedInstance;
+ (SingletonClass *) sharedInstance
{
if (!myVeryOwnSharedInstance)
myVeryOwnSharedInstance = [[self alloc] init];
return myVeryOwnSharedInstance;
}
+ (void) killInstance
{
[myVeryOwnSharedInstance release];
// if release is overridden to do no-op, maybe just invoke -dealloc directly
myVeryOwnSharedInstance = nil;
}
#end
If you want access to your singleton global variable outside of the file in which it's declared, you'll need to make it globally accessible using extern.
At the top of SingletonClass.h, put this:
extern SingletonClass *singletonClassSingleton;
In your SingletonClass.m, use this:
SingletonClass *singletonClassSingleton = nil;
Then assuming you have #import "SingletonClass.h" in your unit test .m file, you should be able to add:
#implementation SingletonClass(Unit Testing Additions)
+ (void)killInstance
{
[singletonClassSingleton release], singletonClassSingleton = nil;
}
#end
The reason I've renamed singleton to singletonClassSingleton is that the variable is now global - if you have a bunch of singleton classes, you need these variables to have unique names, like dataManagerSingleton, resourceManagerSingleton or whatever.
Here is my own solution.
#implementation SingletonClass(Unit Testing Additions)
//Override
static SingletonClass *singleton;
+ (void)killInstance
{
// I get an error here and I cannot access the singleton Object
[singleton release], singleton = nil;
}
//Override
+ (SingletonClass*)sharedInstance
{
if (!singleton)
{
singleton = [[SingletonClass alloc] init];
}
return singleton;
}
#end
Let's say I need to communicate with a class that provides a protocol and calls delegate methods when an operation is complete, as so:
#protocol SomeObjectDelegate
#required
- (void)stuffDone:(id)anObject;
- (void)stuffFailed;
#end
#interface SomeObject : NSObject
{
}
#end
Now, I've decided that while I could make another class implement the stuffDone: delegate method, I've decided that I'd rather encapsulate the process into a block which is written somewhere close to where SomeObject is instantiated, called, etc. How might I do this? Or in other words, if you look at this famous article on blocks (in the Replace Callbacks section); how might I write a method in SomeObject that accepts a completionHandler: of sorts?
It sounds like you wish to communicate with an existing class which is designed to take a delegate object. There are a number of approaches, including:
using a category to add block-based variants of the appropriate methods;
use a derived class to add the block-based variants; and
write a class which implements the protocol and calls your blocks.
Here is one way to do (3). First let's assume your SomeObject is:
#protocol SomeObjectDelegate
#required
- (void)stuffDone:(id)anObject;
- (void)stuffFailed;
#end
#interface SomeObject : NSObject
{
}
+ (void) testCallback:(id<SomeObjectDelegate>)delegate;
#end
#implementation SomeObject
+ (void) testCallback:(id<SomeObjectDelegate>)delegate
{
[delegate stuffDone:[NSNumber numberWithInt:42]];
[delegate stuffFailed];
}
#end
so we have some way to test - you will have a real SomeObject.
Now define a class which implements the protocol and calls your supplied blocks:
#import "SomeObject.h"
typedef void (^StuffDoneBlock)(id anObject);
typedef void (^StuffFailedBlock)();
#interface SomeObjectBlockDelegate : NSObject<SomeObjectDelegate>
{
StuffDoneBlock stuffDoneCallback;
StuffFailedBlock stuffFailedCallback;
}
- (id) initWithOnDone:(StuffDoneBlock)done andOnFail:(StuffFailedBlock)fail;
- (void)dealloc;
+ (SomeObjectBlockDelegate *) someObjectBlockDelegateWithOnDone:(StuffDoneBlock)done andOnFail:(StuffFailedBlock)fail;
// protocol
- (void)stuffDone:(id)anObject;
- (void)stuffFailed;
#end
This class saves the blocks you pass in and calls them in response to the protocol callbacks. The implementation is straightforward:
#implementation SomeObjectBlockDelegate
- (id) initWithOnDone:(StuffDoneBlock)done andOnFail:(StuffFailedBlock)fail
{
if (self = [super init])
{
// copy blocks onto heap
stuffDoneCallback = Block_copy(done);
stuffFailedCallback = Block_copy(fail);
}
return self;
}
- (void)dealloc
{
Block_release(stuffDoneCallback);
Block_release(stuffFailedCallback);
[super dealloc];
}
+ (SomeObjectBlockDelegate *) someObjectBlockDelegateWithOnDone:(StuffDoneBlock)done andOnFail:(StuffFailedBlock)fail
{
return (SomeObjectBlockDelegate *)[[[SomeObjectBlockDelegate alloc] initWithOnDone:done andOnFail:fail] autorelease];
}
// protocol
- (void)stuffDone:(id)anObject
{
stuffDoneCallback(anObject);
}
- (void)stuffFailed
{
stuffFailedCallback();
}
#end
The only thing you need to remember is to Block_copy() the blocks when initializing and to Block_release() them later - this is because blocks are stack allocated and your object may outlive its creating stack frame; Block_copy() creates a copy in the heap.
Now you can all a delegate-based method passing it blocks:
[SomeObject testCallback:[SomeObjectBlockDelegate
someObjectBlockDelegateWithOnDone:^(id anObject) { NSLog(#"Done: %#", anObject); }
andOnFail:^{ NSLog(#"Failed"); }
]
];
You can use this technique to wrap blocks for any protocol.
ARC Addendum
In response to the comment: to make this ARC compatible just remove the calls to Block_copy() leaving direct assignments:
stuffDoneCallback = done;
stuffFailedCallback = fail;
and remove the dealloc method. You can also change Blockcopy to copy, i.e. stuffDoneCallback = [done copy];, and this is what you might assume is needed from reading the ARC documentation. However it is not as the assignment is to a strong variable which causes ARC to retain the assigned value - and retaining a stack block copies it to the heap. Therefore the ARC code generated produces the same results with or without the copy.
You could do something like this:
typedef void (^AZCallback)(NSError *);
AZCallback callback = ^(NSError *error) {
if (error == nil) {
NSLog(#"succeeded!");
} else {
NSLog(#"failed: %#", error);
}
};
SomeObject *o = [[SomeObject alloc] init];
[o setCallback:callback]; // you *MUST* -copy the block
[o doStuff];
...etc;
Then inside SomeObject, you could do:
if ([self hadError]) {
callback([self error]);
} else {
callback(nil);
}
The below link explains how the call backs using delegates could be easily replaced with blocks.
The examples includes UITableview,UIAlertview and ModalViewController.
click me
Hope this helps.
Would you call this implementation of a multiton in objective-c 'elegant'? I have programmatically 'disallowed' use of alloc and allocWithZone: because the decision to allocate or not allocate memory needs to be done based on a key.
I know for sure that I need to work with only two instances, so I'm using 'switch-case' instead of a map.
#import "Multiton.h"
static Multiton *firstInstance = nil;
static Multiton *secondInstance = nil;
#implementation Multiton
+ (Multiton *) sharedInstanceForDirection:(enum KeyName)direction {
return [[self allocWithKey:direction] init];
}
+ (id) allocWithKey:(enum KeyName)key {
return [self allocWithZone:nil andKey:key];
}
+ (id) allocWithZone:(NSZone *)zone andKey:(enum KeyName)key {
Multiton **sharedInstance;
#synchronized(self) {
switch (key) {
case KEY_1:
sharedInstance = &firstInstance;
break;
case KEY_2:
sharedInstance = &secondInstance;
break;
default:
[NSException raise:NSInvalidArgumentException format:#"Invalid key"];
break;
}
if (*sharedInstance == nil)
*sharedInstance = [super allocWithZone:zone];
}
return *sharedInstance;
}
+ (id) allocWithZone:(NSZone *)zone {
//Do not allow use of alloc and allocWithZone
[NSException raise:NSObjectInaccessibleException format:#"Use allocWithZone:andKey: or allocWithKey:"];
return nil;
}
- (id) copyWithZone:(NSZone *)zone {
return self;
}
- (id) retain {
return self;
}
- (unsigned) retainCount {
return NSUIntegerMax;
}
- (void) release {
return;
}
- (id) autorelease {
return self;
}
- (id) init {
[super init];
return self;
}
#end
PS: I've not tried out if this works as yet, but its compiling cleanly :)
I find singletons a bad idea and this looks about four times as horrible. The code is quite complex, you can be sure of spending a nice few hours chasing subtle bugs in it and you will probably never feel comfortable about it. That’s no good. You should throw this abomination away and wire your objects together in some other way that doesn’t require so much thinking.
If you like patterns, you can use something akin to Factory pattern to wire your objects. The Factory will take care of creating those two instances and passing them wherever needed. And the Factory will be a lot more simple than Multiton:
#interface Factory : NSObject {
Foo *foo1, *foo2;
}
#end
#implementation Factory
- (id) init {
[super init];
foo1 = [[Foo alloc] init];
foo2 = [[Foo alloc] init];
return self;
}
Of course you don’t have to create both instances at once. You can do anything you like there – cache, lazy load, anything. The point is leaving the Foo lifetime management up to the Factory, separate from the Foo code. Then it gets much easier. ¶ All the other objects that need Foo will be created and wired through Factory and will receive their Foo through a setter:
#implementation Factory
- (id) wireSomeClass {
id instance = [[SomeClass alloc] init];
[instance setFoo:foo1];
[instance setAnotherDependency:bar];
return [instance autorelease];
}
This is all much more straightforward then the code from your question.
Don't override alloc. The problem with overriding alloc to return a previously allocated instance of the class, as you do, is that when +sharedInstance calls [[Multiton alloc] init]... +alloc will return the old instance, then -init will re-initialize it! The best practice is to override -init, doing the cache lookup and calling [self release] before you return the cached instance.
If you're really concerned about the cost of that extra +alloc (it's not much), you also do your cache lookup in +sharedInstance and then ensure that all of your clients access the instance through +sharedInstance to avoid the extra alloc.
Point of order: How do you know that you'll only ever have two instances, or need to have two instances? (Or want to have two instances?) What, exactly, is the point of having a "Multiton"? (And is that even a word?)