16

PromiseKit 在其网站上声明以下内容:

我应该担心保留周期吗?

tl; dr:在 promise 处理程序中使用 self 是安全的。

这是安全的:

somePromise.then {
    self.doSomething()
}

如果somePromise解析,传递给的函数then将被释放,因此[weak self]不需要指定。

指定 [unowned self] 可能很危险。

你是在告诉我不要担心保留周期?!

不,只是默认情况下,在使用 PromiseKit 时不会导致保留周期。但是还是有可能的...

这是否意味着我永远不应该[weak self]在 PromiseKit 块中使用?有没有我仍然需要使用的情况[weak self]?它究竟是如何防止保留周期的?

4

2 回答 2

19

TL;DR:继续使用[weak self]PromiseKit 块来防止对象的寿命超过必要的时间。


有几点需要注意。首先,在块中使用有两个主要原因[weak self]

  1. 防止保留循环
  2. 防止物体的寿命超过必要的时间

其次,当您调用该代码块时,PromiseKit会创建一个保留周期。self通常坚持somePromise,并且somePromise坚持self。他们说你不应该关心这个保留周期的原因是因为保留周期会被 PromiseKit 自动破坏。当then被释放时,somePromise将不再持有self,从而打破了保留周期。

所以我们知道我们不需要担心 PromiseKit 块的问题 #1,但是问题 #2 呢?

想象一下,一个视图控制器触发了一个网络请求承诺,并且需要 30 秒才能解决这个承诺。现在在它解决之前,用户按下后退按钮。通常 UIKit 会释放视图控制器,因为它不再在屏幕上并且系统可以节省资源。但是,由于您self在 Promise 中引用,它不能再被释放。这意味着视图控制器在内存中的寿命将比必要的长 30 秒。

解决问题 #2 的唯一方法是[weak self]在块内使用。

注意:有人可能会争辩说,当您的视图控制器退出时,您无论如何都应该取消正在进行的承诺,以便它释放对self. 然而,弄清楚何时应该释放视图控制器并不是一项简单的任务。让 UIKit 为您处理逻辑要容易得多,如果您在视图控制器被释放时确实需要做任何事情,请在视图控制器的dealloc方法中实现它。如果块强烈地保持在视图控制器上,这将不起作用。


更新:看起来其中一位作者确实谈到了这一点,并阐明了提出这些建议的原因:

事实上,保留self可能是您想要的,以便在self释放之前解决承诺。

于 2016-09-01T21:34:24.213 回答
14

该文档只是说您不必担心 PromiseKit 引入“强引用周期”(以前称为“保留周期”),因为当承诺完成并且块完成运行时,这些强引用会自动为您解决. 强引用与弱引用的选择完全取决于您。

例如,如果您只是在场景中更新不再存在的 UI 元素,则无需保留对已关闭视图控制器的强引用。你会weak在那种情况下使用。但有时您需要强引用(例如,您可能希望更新底层模型以反映承诺的成功或失败)。

归根结底,他们只是说你不应该让 PromiseKit 决定强引用和弱引用,而应该由你的应用程序更广泛的设计要求来驱动。PromiseKit 唯一的硬性规则是你应该避免unowned.

于 2016-09-01T22:09:03.700 回答