Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
424 views
in Technique[技术] by (71.8m points)

objective c - Singleton in iOS 5?

Hi I had an implementation previous versions of iOS for a singleton as follows:

.h file

@interface CartSingleton : NSObject 
{

}
+(CartSingleton *) getSingleton;

.m file

@implementation CartSingleton

static CartSingleton *sharedSingleton = nil;

+(CartSingleton *) getSingleton
{
    if (sharedSingleton !=nil)
       {
        NSLog(@"Cart has already been created.....");
        return sharedSingleton;
       }
    @synchronized(self)
   {
    if (sharedSingleton == nil)
       {
        sharedSingleton = [[self alloc]init];
        NSLog(@"Created a new Cart");
       }
   }
    return sharedSingleton;
}
//==============================================================================
+(id)alloc
{
    @synchronized([CartSingleton class])
   {
    NSLog(@"inside alloc");
    NSAssert(sharedSingleton == nil, @"Attempted to allocate a second instance of a singleton.");
    sharedSingleton = [super alloc];
    return sharedSingleton;
   }

    return nil;
}

//==============================================================================
-(id)init
{
    self = [super init];
}

However on the web I see people have implemented the Singleton design pattern using this code:

+ (id)sharedInstance
{
  static dispatch_once_t pred = 0;
  __strong static id _sharedObject = nil;
  dispatch_once(&pred, ^{
    _sharedObject = [[self alloc] init]; // or some other init method
  });
  return _sharedObject;
}

Could someone who is experience please guide me. Im a newbie and thoroughly confused between the old iOS implementation of the Singleton and the new one and which is the correct one?

Thanks a lot

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Strictly speaking, you must use:

+ (MySingleton*) instance {
     static dispatch_once_t _singletonPredicate;
     static MySingleton *_singleton = nil;

     dispatch_once(&_singletonPredicate, ^{
        _singleton = [[super allocWithZone:nil] init];
     });

     return _singleton;
 }

 + (id) allocWithZone:(NSZone *)zone {
      return [self instance];
 }

Now you guarantee that one cannot call alloc/init and create another instance.

Explanation: The instance method is at the class level and is your main access method to get a reference to the singleton. The method simply uses the dispatch_once() built-in queue that will only execute a block once. How does the runtime guarantee that the block is only executed once? Using the predicate you supply (of type dispatch_once_t). This low-level call will guarantee that even if there are multiple threads trying to call it, only one succeeds, the others wait until the first one is done and then returns.

The reason we override allocWithZone is because alloc calls allocWithZone passing nil as the zone (for the default zone). To prevent rogue code from allocating and init-ializing another instance we override allocWithZone so that the instance passed back is the already initialized singleton. This prevents one from creating a second instance.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...