Reputation: 45503
I have created a singleton class to keep track of my data on my iPhone app. I know singleton's only need to be instantiated once, but what is the best place to instantiate it? Should this be done in the appDelegate? I want to be able to call this singleton (which contains an NSMutableArray) from a multitude of classes so that I can have access to the array.
Here is my Class I wrote:
#import "WorkoutManager.h"
static WorkoutManager *workoutManagerInstance;
@implementation WorkoutManager
@synthesize workouts;
+(WorkoutManager*)sharedInstance {
if(!workoutManagerInstance) {
workoutManagerInstance = [[WorkoutManager alloc] init];
}
return workoutManagerInstance;
}
-(id)init {
self = [super init];
if (self) {
workouts = [[NSMutableArray alloc] init];
}
return self;
}
@end
Upvotes: 3
Views: 996
Reputation: 64002
Singletons are generally instantiated lazily -- the first time they are accessed, the instance is created and returned from the access method. Subsequent calls to the access method simply return the already-created instance.
The standard pattern is: 1. Take a lock or otherwise make the following thread-safe (i.e., dispatch_once()
). 2. Check whether the single instance has been created yet. 3. If not, create it. 4. Release lock (if applicable). 5. Return the instance.
It is possible, if you need to for some reason, to create the instance earlier. The class method +load
is sent by the runtime when the class is added to the runtime, which is very early in your app's execution. (+initialize
seems like it's also a candidate -- it is sent by the runtime right before the class recieves its first (other) message (also excluding +load
) -- but it doesn't actually get you anything, since it'll be sent immediately before you send sharedInstance
.)
The gcc __constructor__
function attribute also works (in clang as well), despite being documented as not implemented for ObjC. A function with this attribute will be called before main()
is entered. I'm not too sure about the memory management implications of this option, though. The runtime should be all set up, but there won't be an autorelease pool in place yet.
Upvotes: 2
Reputation: 10045
I'm using this code to instantiate singletons. GCD takes care of synchronization
+ (SingletonClass *)sharedInstance {
static SingletonClass *sharedInstance;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedInstance = [[SingletonClass alloc] init];
sharedInstance.property = [Property new];
});
return sharedInstance;
}
Upvotes: 0
Reputation: 19737
Usually singleton classes are instantiated the first time they are accessed:
static SomeClass *_instance = nil;
+ (SomeClass *) instance {
@synchronized(self) {
if (!_instance)
_instance = [[self alloc] init];
}
return _instance;
}
Upvotes: 0
Reputation: 299455
In almost all cases, the point of a singleton is you don't care who first instantiates it. Whoever is the first to call [Something sharedSomething]
will be the creator. You want to use the pattern given in " How do I implement an Objective-C singleton that is compatible with ARC? " It'll ensure the singleton is created only one time.
Upvotes: 6
Reputation: 54836
This is probably the simplest approach:
static MyClass* theInstance = nil;
+ (MyClass*) sharedInstance {
@synchronized(self) {
if (! theInstance) {
theInstance = [[MyClass alloc] init];
}
}
return theInstance;
}
...so in places where you want to access the singleton, you just do [MyClass sharedInstance]
in order to get a reference to the instance.
Note that this won't protect against people manually calling alloc
and init
on your singleton class to create additional instances. If you need to do that you can implement init
in a manner similar to the above in order to prevent additional instances from being created/returned using alloc
and init
.
In practice, however, singleton classes most commonly use the sharedInstance
approach (sometimes with minor variations in naming, like [UIApplication sharedApplication]
).
Upvotes: 1