3

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
TopChef
  • 43,745
  • 10
  • 28
  • 27
  • check out this: http://stackoverflow.com/questions/145154/what-does-your-objective-c-singleton-look-like – Chris Cooper Apr 11 '12 at 00:46
  • or this: http://stackoverflow.com/questions/7568935/how-do-i-implement-an-objective-c-singleton-that-is-compatible-with-arc – Chris Cooper Apr 11 '12 at 00:47
  • The links seem to be about implementing a Singleton. I already have mine written and functioning. I instantiate it within one an IBAction in one of my classes, however i'm confused about whether or not I should instantiate it elsewhere so that it is global? – TopChef Apr 11 '12 at 00:49
  • 2
    The point of those answers is that you don't have to instantiate it anywhere in your code. The first time you go to use it, it will automatically be instantiated. – Chris Cooper Apr 11 '12 at 00:51
  • Even if it is used within something like an IBAction? Or should it be instantiated in a class header? – TopChef Apr 11 '12 at 00:55

5 Answers5

6

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.

Community
  • 1
  • 1
Rob Napier
  • 286,113
  • 34
  • 456
  • 610
2

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.

jscs
  • 63,694
  • 13
  • 151
  • 195
  • Very useful techniques here. `+load` is a particularly useful tool to know about (though you shouldn't need it very often). – Rob Napier Apr 11 '12 at 00:54
1

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

aroth
  • 54,026
  • 20
  • 135
  • 176
  • 1
    I recommend the GCD pattern given in the answer to http://stackoverflow.com/questions/7568935/how-do-i-implement-an-objective-c-singleton-that-is-compatible-with-arc. The @synchronize solution is a bit more expensive to call, and there's no reason to pay that cost since the addition of dispatch_once. – Rob Napier Apr 11 '12 at 00:52
  • Either approach will work, yes. Personally I prefer `@synchronized`; I just think it's a bit more readable. – aroth Apr 11 '12 at 00:55
0

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;
}
SundayMonday
  • 19,147
  • 29
  • 100
  • 154
0

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;
}
Eugene
  • 10,006
  • 4
  • 37
  • 55