Correct Singleton Pattern Objective C (iOS)?
Keep it simple:
+(instancetype)sharedInstance
{
static dispatch_once_t pred;
static id sharedInstance = nil;
dispatch_once(&pred, ^{
sharedInstance = [[self alloc] init];
});
return sharedInstance;
}
- (void)dealloc
{
// implement -dealloc & remove abort() when refactoring for
// non-singleton use.
abort();
}
That is it. Overriding retain
, release
, retainCount
and the rest is just hiding bugs and adding a bunch of lines of unnecessary code. Every line of code is a bug waiting to happen. In reality, if you are causing dealloc
to be called on your shared instance, you have a very serious bug in your app. That bug should be fixed, not hidden.
This approach also lends itself to refactoring to support non-singleton usage modes. Pretty much every singleton that survives beyond a few releases will eventually be refactored into a non-singleton form. Some (like NSFileManager
) continue to support a singleton mode while also supporting arbitrary instantiation.
Note that the above also "just works" in ARC.
What should my Objective-C singleton look like?
Another option is to use the +(void)initialize
method. From the documentation:
The runtime sends
initialize
to each class in a program exactly one time just before the class, or any class that inherits from it, is sent its first message from within the program. (Thus the method may never be invoked if the class is not used.) The runtime sends theinitialize
message to classes in a thread-safe manner. Superclasses receive this message before their subclasses.
So you could do something akin to this:
static MySingleton *sharedSingleton;
+ (void)initialize
{
static BOOL initialized = NO;
if(!initialized)
{
initialized = YES;
sharedSingleton = [[MySingleton alloc] init];
}
}
What is the use of Singleton class in objective-c?
A singleton is a special kind of class where only one instance of the class exists for the current process. In the case of an iPhone app, the one instance is shared across the entire app.
Have a look at these tutorials :
http://pixeleap.com/?p=19
http://www.codeproject.com/Tips/232321/Implement-Objective-C-Singleton-Pattern
http://xcodenoobies.blogspot.in/2012/08/how-to-pass-data-between.html
http://www.johnwordsworth.com/2010/04/iphone-code-snippet-the-singleton-pattern/
http://www.idev101.com/code/Objective-C/singletons.html
And this video tutorial :
http://www.youtube.com/watch?v=FTfEN8KQPK8
How to create singleton class in objective C
Okay appDev, you will probably find quite a few different techniques to do this on the web. However, for iOS app development, I think the most convenient way is to do the following:
Write your method(s) for getting the singleton object. (Recommendation: use
dispatch_once
thread and GCD for this).Wrap your method(s) in a macro and add it to your
$Project$-Prefix.pch
file.Call the one line macro whenever you need singleton object for a class.
Example:
CommonMacros.h:
#define SINGLETON_FOR_CLASS(classname)
+ (id) shared##classname {
static dispatch_once_t pred = 0;
static id _sharedObject = nil;
dispatch_once(&pred, ^{
_sharedObject = [[self alloc] init];
});
return _sharedObject;
}
YourProject-Prefix.pch:
...
#import "CommonMacros.h"
...
YourSingletonClass.m:
...
SINGLETON_FOR_CLASS(YourSingletonClass)
...
The use of singleton class in objective c and swift
To me it seems you do not need a singleton at all. I suggest you would be best of redesigning the architecture to have a user class that can store the information you are needing (and more if you finds the need in the future).
Then you could either pass that user object around between the view controllers as they need or perhaps easier define a currentUser property for the app delegate class.
That way each view controller can obtain the app delegate from the NSApp global reference to the application object and then get the current user object from there. With this pattern the app delegate acts as the globally accessible singleton you need without any need to manage it yourself.
Singleton with parameter iOS
There are a number of problem in this design:
As recommended by Apple, should
dispatch_once
instead of@synchronized(self)
for singleton:static MyClass *sharedInstance = nil;
static dispatch_once_t onceToken = 0;
dispatch_once(&onceToken, ^{
sharedInstance = [[MyClass alloc] init];
// Do any other initialisation stuff here
});
return sharedInstance;Refer to this question for more detail: Why does Apple recommend to use dispatch_once for implementing the singleton pattern under ARC?
Bad
API
design to put singleton inalloc
.As indicated by the name of the method
alloc
, it means that some memory will be allocated. However, in your case, it is not. This attempt to overwrite thealloc
will cause confusion to other programmers in your team.Bad idea to use
NSAssert
in your-init
.If you want to disable a method, disable it by putting this in your header file:
- (id)init __attribute__((unavailable));
In this case, you will get a compile error instead of crashing the app at run time.
Refer to this post for more detail: Approach to overriding a Core Data property: isDeletedMoreover, you can even add unavailable message:
- (id)init __attribute__((unavailable("You cannot init this class directly. It needs UserAccountDataSource as a parameter")));
Sometime input parameters is ignored with no warning.
In your following code, how would the programmer who is calling this function know that the input parameter
userAccount
is sometimes ignored if an instance of the class is already created by someone else?- (id)sharedInstanceWithAccount:(UserAccount *)userAccount {
if (!sharedInstance) {
@synchronized(self) {
sharedInstance = [[[self class] alloc] initWithAccount:userAccount];
}
}
return sharedInstance;
}
In short, don't think it is a good idea to create singleton with parameter. Use conventional singleton design is much cleaner.
How do I implement an Objective-C singleton that is compatible with ARC?
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;
}
Singleton Object in iOS
You can forbid calls of init
with such trick:
add - (instancetype)init NS_UNAVAILABLE;
definition to your singleton interface.
Instead of [[PhotoManager alloc] init];
use [[[self class] alloc] init];
PhotoManager *sharedManager = [[PhotoManager alloc] init];
won't compile.
There is my example:
@interface SomeSingleton : NSObject
+ (instancetype)sharedInstance;
- (instancetype)init NS_UNAVAILABLE;
@end
@implementation SomeSingleton
+ (instancetype)sharedInstance {
static dispatch_once_t onceToken;
static SomeSingleton *instance;
dispatch_once(&onceToken, ^{
instance = [[[self class] alloc] init];
});
return instance;
}
- (instancetype)init {
self = [super init];
return self;
}
@end
As result SomeSingleton *s1 = [SomeSingleton sharedInstance];
works, but SomeSingleton *s2 = [[SomeSingleton alloc] init];
leads to the compile error.
Related Topics
How to Debug iOS 8 Extensions With Nslog
How to Handle Background Audio Playing While iOS Device Is Locked or on Another Application
Add "...Read More" to the End of Uilabel
Get Indexpath of Uitableviewcell on Click of Button from Cell
Swrevealviewcontroller Without Using Navigationcontroller
How to Allow Didset to Be Called During Initialization in Swift
I Have Real Misunderstanding With Mfmailcomposeviewcontroller in Swift (Ios8) in Simulator
How to Locate the Cgrect For a Substring of Text in a Uilabel
Allow Only Numbers For Uitextfield Input
How to Upload Images to a Server in iOS With Swift
Command Failed Due to Signal: Segmentation Fault: 11
Why Is Wkwebview Not Opening Links With Target="_Blank"
How to Launch Safari and Open Url from iOS App
What Kind of Leaks Does Automatic Reference Counting in Objective-C Not Prevent or Minimize