iOS单例

来源:互联网 发布:thesaurus 知乎 编辑:程序博客网 时间:2024/06/06 00:13

static MyGizmoClass *sharedGizmoManager = nil;
+ (MyGizmoClass*)sharedManager{   if (sharedGizmoManager == nil)  {   sharedGizmoManager = [[super allocWithZone:NULL] init];   }   return sharedGizmoManager;}
+ (id)allocWithZone:(NSZone *)zone{   return [[self sharedManager] retain];}
- (id)copyWithZone:(NSZone *)zone{   return self;}
- (id)retain{   return self;}
- (NSUInteger)retainCount{   return NSUIntegerMax;  //denotes an object that cannot be released}
- (void)release{   //do nothing}
- (id)autorelease{   return self;}

 

 

我们需要重写一些方法:

 
- (id)retain 

    return self; 

 
- (NSUInteger) retainCount 

    return NSUIntegerMax; 

 
- (void) release 

    // do nothing 

 
- (id)autorelease 

    return self; 

 在retain和autorelease什么都不做只是返回自己,release的时候啥都不做,将retainCount设为UInt的极大值。

 

 其次是关于线程安全的实现,这些java都有明确的代码模式:

 关于线程安全的单例,这篇外文 http://www.numbergrinder.com/2008/12/patterns-in-objective-c-singleton-pattern/ 有比较详细的解释。

 

 @implementation Singleton 
static Singleton *instance = nil; 
+ (Singleton *)sharedInstance  { 
   @synchronized(self)  
   { 
        if(!instance) { 
           instance = [[Singleton alloc] init]; 
        } 
    } 
  
    return instance; 

  
@end 
  

嗯,这样就可以实现线程安全的单例了,当然这里也可以用NSLock实例去实现。

 

最后趁机深入了下单例模式,发现instance = [[Singleton alloc] init];这样的语句是有问题的,它不能以其他方式发起分配内存去实例化对象,可能会造成多个实例被创建。(见《pro objective-c design patterns for ios》 )

该书推荐用

 
 
instance = [[super allocWithZone:NULL] init]; 
  

传NULL到allocWithZone其实等同与alloc默认方法,但注意这里是调用super的alloc;

 

本类的allocWithZone被改写为:

 
 
+ (id)allocWithZone:(NSZone *)zone 

      return [self sharedInstance]; 

 
- (id)copyWithZone:(NSZone *)zone 

      return self; 

 同时深拷贝也直接重载阻止掉多个实例的出现。上面的allocWithZone的重载使得这个单例也能够直接用alloc或是allocWithZone进行初始化,但返回的一如既往是那个static的实例。