2
\$\begingroup\$

Is this the right way to do a singleton in Objective-C (coming from an Android background, with a little understanding of threading)?

#import "ItemsManager.h"

#define kNumMaxSelectableItems 15

@implementation ItemsManager{
    NSMutableArray *currentItems;
}

static ItemsManager *myself;

-(id)init{
    if(self=[super init]){
        currentItems = [[NSMutableArray alloc] initWithCapacity:kNumMaxSelectableItems];
        myself = self;
    }
    return self;
}

+(ItemsManager *)getInstance{
    if(!myself){
        myself = [[ItemsManager alloc] init];
    }
    return myself;
}

-(void) doSomething{
    NSLog(@"hi");
}

-(void)dealloc{
    [currentItems release];
    currentItems = nil;
    myself = nil;

    [super dealloc];
}

@end

And with this design, I suppose I would call it like:

void main(){
    [[ItemsManager getInstance] doSomething];
}
\$\endgroup\$
9
\$\begingroup\$

This is the the way singletons are usually implemented in apple's code samples.

+ (ItemsManager *)sharedInstance
{
    static ItemsManager *sharedInstance = nil;
    static dispatch_once_t once;

    /* Doing the allocation inside dispatch_once queue ensures the code
       will run only once for the lifetime of the app. */

    dispatch_once(&once, ^{
        sharedInstance = [[ItemsManager alloc] init];
    });

    return sharedInstance;
}
\$\endgroup\$
3
\$\begingroup\$

how do i hide the init method so that no one else can alloc/init my class without using "getInstance"?

there is not a widely accepted pattern how to do so.
In fact many (not only Objective-C) developer would argue today, that a classical strict Singleton is not needed and even harmful [1], [2], [3] — first of all Singletons make code hard to test, as the introduce global states and unit tests might yield different results if their order is changed.

Also Apple changed many real singleton in older Cocoa-Implementations to the softer shared instance pattern, in which actually many objects can be instantiated, but the class offers one shared one — and this is what dallen posted.

conclusion
Don't waste your time to try to make a bullet-proof singleton. It just don't worth the hassle. Use the approach dallen showed you and when it comes to unit testing be happy, that you can instantiate new objects.


that said: in the book "Objective-C Design Patterns for iOS", chapter 7, Carlo Chung shows an implementation of an Singleton, that is even sub-classable. But also in that chapter Chung points out the problems about singleton and advises to use the shared instance concept. Beware: that code predates ARC.

\$\endgroup\$
  • 1
    \$\begingroup\$ Note though, that it's not necessary to add a public init to production code, just to allow it to be used for unit test. \$\endgroup\$ – Nate May 24 '13 at 21:39

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.