2014-10-31 78 views
1

这与标准singleton pattern稍有不同,因为如果所有对象的外部引用都已释放,那么单例也将被释放。然后,稍后,当请求一个新的对象时,将创建一个新的单例。所以,这样的事情:如何确保Objective-C中任何时候只有一个类的实例?

MyThing *thing1 = [MyThing new]; 
MyThing *thing2 = [MyThing new]; 
// thing1 & thing2 are the same object. 

thing1 = nil; 
thing2 = nil; 

thing1 = [MyThing new]; 
thing2 = [MyThing new]; 
// thing1 and thing2 are a the same objet, but it's a different object than above. 

我试图用微弱的静态变量来挂在我的范围的单,但没有工作,因为我没有办法来增加ARC下的保留计数。这让我想知道:这甚至有可能吗?

+0

为什么你需要这个? – Abizern 2014-10-31 21:18:05

+1

看起来像通过工厂访问的弱引用会做到这一点。工厂必须像单身工厂一样工作。 – 2014-10-31 21:21:38

+0

因为我不会经常需要这个对象,但是当我这样做时,我会想要一次访问一堆分离的地方中的同一个对象。 – theory 2014-10-31 21:21:52

回答

1

重写allocWithZone:管理单个静态实例。如果无,则创建一个新的,如果不是零,则返回它的保留版本。

实现dealloc和当调用nil时的单个静态实例。

我不确定这是否适用于ARC,您可能需要为该文件禁用弧。

保持物体周围的代价有多昂贵?遵循标准的单例模式并忘记它,肯定没那么麻烦。

+0

您还需要修改'init',以便在您获得已存在的对象时不会重新初始化。 – 2014-10-31 21:36:15

+0

是的,这似乎是正确的答案。我在'-init'中执行了它,但移动了它'+ allocWithZone:',现在它按预期工作。现在只需要弄清楚如何让'-init'对现有对象不做任何事情...... – theory 2014-10-31 21:52:39

+0

我想我已经明白了,虽然它不是通用化的(检查是否在'-init'中设置了ivar)。测试通过,但是在释放对象之后,在创建新对象之前,我必须调用'NSLog()'或者取回具有相同地址的对象。即使使用NSLog(),我仍然有时会在同一个地址获得一个对象。 – theory 2014-10-31 22:04:25

0

基于@ KirkSpaziani的答案,这是我想出来的:

static __weak MyTHing *currentThing = nil; 

+ (instancetype)allocWithZone:(struct _NSZone *)zone { 
    __block id thing = nil; 
    dispatch_sync(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ 
     if (currentThing == nil) { 
      currentThing = thing = [super allocWithZone:zone]; 
     } else { 
      thing = currentThing; 
     } 
    }); 
    return thing; 
} 

- (void)dealloc { 
    dispatch_sync(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ 
     currentThing = nil; 
    }); 
} 

这假设初始值设定处理“脏数据”,作为described by Mike Ash

+0

现在,如果只有我可以阻止Objective-C在objet发布后使用相同的内存地址,我可以进行一个很好的测试以确保它能正常工作。实际上,我可以通过添加一个'NSLog()'调用的日志来看到它的工作原理,但我会更加乐于进行可靠的单元测试。 – theory 2014-10-31 22:51:42

+0

你应该看看http://stackoverflow.com/questions/7274360/how-objective-c-singleton-should-implement-init-method – rmaddy 2014-10-31 23:47:30

+0

登录dealloc?这应该是最可靠的方法。此外,如果多个线程可以创建这些对象,请考虑使用GCD的dispatch_sync而不是@synchronized(self) - 它应该更具性能。 – KirkSpaziani 2014-11-01 22:23:02

相关问题