Cocoa dispatch_once 每个实例
Posted
技术标签:
【中文标题】Cocoa dispatch_once 每个实例【英文标题】:Cocoa dispatch_once per instance 【发布时间】:2014-08-08 10:29:11 【问题描述】:如何使用dispatch_once,
,以便给定代码在每个实例生命周期内执行一次。
相当于在对象内部拥有一个属性,并像这样使用它:
- (void)viewWillAppear:(..)..
// ...
if (self.isDispatched == NO)
// ...
self.isDispatched = YES;
但我不想使用额外的属性,而是 dispatch_once_t
或类似的。
【问题讨论】:
为什么不能在init方法或viewDidLoad
方法中运行代码?
因为它需要在 viewWillAppear 运行 :)
无论您使用标志还是dispatch_once_t
,它都必须是实例变量(这与属性不同)。而且,是的,您可以使用 dispatch_once_t
作为实例变量,尽管经常有相反的说法。
你能发布一些代码作为答案吗?
你为什么还要使用dispatch_once
呢?它对于处理线程安全很有用,但viewWillAppear
方法将始终在主线程上调用。根据 KISS 原则,我认为在这种情况下 BOOL 属性已经足够好了。或者你可以在某些情况下使用延迟初始化的属性(这取决于你想在viewWillAppear
中做什么)。
【参考方案1】:
无法满足您的要求。 dispatch_once
只能用于以前从未写入过的内存,并且您无法通过实例变量来保证这一点。 Greg Parker says so,他会知道的。
改为使用问题中的代码,但将其包装在 @synchronized
块中。
如果您真的想避免添加实例变量,您可以使用单独的单例来管理可变集。您必须向它注册实例并在解除分配时将其删除。确保这个助手类只保存弱引用;见NSMapTable
和NSMapTableWeakMemory
。
【讨论】:
【参考方案2】:对于那些好奇并作为额外提示的人,对我来说,这种方法对此很有用:
class SomeVC : UIViewController
private var token: dispatch_once_t = 0
public override func viewDidAppear(animated: Bool)
super.viewDidAppear(animated)
dispatch_once(&token) () -> Void in
self.doSomethingOnce()
通过不声明静态变量,它具有预期的行为。话虽如此,这绝对不推荐用于任何严肃的项目,因为在文档中(正如您所说的那样)它指出:
谓词必须指向存储在全局或静态范围内的变量。使用带有自动或动态存储(包括 Objective-C 实例变量)的谓词的结果是未定义的。
如果我们不想在未来遇到任何奇怪的错误和未定义的行为,我会坚持 Apple 所说的。但是玩这些东西还是不错的,不是吗? =)
【讨论】:
+一个用于注意“谓词必须指向存储在全局或静态范围内的变量。”以上是关于Cocoa dispatch_once 每个实例的主要内容,如果未能解决你的问题,请参考以下文章
为啥苹果推荐使用 dispatch_once 来实现 ARC 下的单例模式?