我经常这样做
let when = DispatchTime.now() + 2.0 DispatchQueue.main.asyncAfter(deadline: when) { beep() }
在一个应用程序中,我们经常这样做
tickle.fresh(){ msg in paint() }
但如果你做 这个
let when = DispatchTime.now() + 2.0 DispatchQueue.main.asyncAfter(deadline: when) { tickle.fresh(){ msg in paint() } }
当然,你必须做 这个
let when = DispatchTime.now() + 2.0 DispatchQueue.main.asyncAfter(deadline: when) { [weak self] _ in tickle.fresh(){ msg in self?.paint() } }
或者,也许 这
let when = DispatchTime.now() + 2.0 DispatchQueue.main.asyncAfter(deadline: when) { tickle.fresh(){ [weak self] msg in self?.paint() } }
也许这
let when = DispatchTime.now() + 2.0 DispatchQueue.main.asyncAfter(deadline: when) { [weak self] _ in tickle.fresh(){ [weak self] msg in self?.paint() } }
所有这三个建议 似乎都 可以正常工作。这里的完整含义是什么?那该怎么办?强引用是弱引用,弱引用还是强引用?生存还是毁灭?这就是问题所在!
首先,请注意DispatchQueue.main.asyncAfter,由于闭包将在 某个 时刻执行,因此您通常不必担心使用保留周期。因此,无论您是否弱捕获了self,都不会创建一个永久的保留周期(假设tickle.fresh也没有)。
DispatchQueue.main.asyncAfter
self
tickle.fresh
是否[weak self]在外部asyncAfter闭包上放置捕获列表完全取决于是否要self保留直到调用闭包(设置时间之后)。如果self在调用闭包之前不需要保持活动状态,请放入[weak self],如果这样做,则不要放入。
[weak self]
asyncAfter
是否[weak self]在内部闭合上放置一个(传递给的tickle.fresh)取决于您是否已经弱捕获self外部闭合。如果没有,则可以放置[weak self]以防止内部封闭保留它。但是,如果外部封闭已被弱捕获self,则内部封闭将 已经 具有弱引用self,因此添加[weak self]到内部封闭将无效。
因此,总结一下:
DispatchQueue.main.asyncAfter(deadline: .now() + 2) { tickle.fresh { msg in self.paint() } }
self 将由外部和内部封闭保留。
DispatchQueue.main.asyncAfter(deadline: .now() + 2) { [weak self] in tickle.fresh { msg in self?.paint() } }
self 不会被任何一个关闭保留。
DispatchQueue.main.asyncAfter(deadline: .now() + 2) { [weak self] in tickle.fresh { [weak self] msg in self?.paint() } }
与上述相同,[weak self]用于内部封闭件的附加件没有作用,因为self外部封闭件已经很弱地捕获了附加件。
DispatchQueue.main.asyncAfter(deadline: .now() + 2) { tickle.fresh { [weak self] msg in self?.paint() } }
self 将由外部封闭物保留,而不由内部封闭物保留。
当然,可能您不想self被外部闭包保留,但是您 确实 希望被内部闭包保留。在这种情况下,您可以在外部闭包中声明一个局部变量,以便持有对的强引用self,然后才能在内部闭包中进行捕获:
DispatchQueue.main.asyncAfter(deadline: .now() + 2) { [weak self] in guard let strongSelf = self else { return } tickle.fresh { msg in strongSelf.paint() } }
现在,self外部闭包将不会保持活动状态,但是一旦调用它(如果self仍然存在),内部闭包将使其保持活动状态,直到该闭锁被释放为止。
回应:
强引用是弱引用,弱引用还是强引用?
弱引用作为值类型的可选实现。因此,您不能 直接 引用一个实例,而是必须先对其进行拆包,然后再对该实例进行引用。在这种情况下,您只是在处理强大的参考(与我上面的示例完全一样strongSelf)。
strongSelf
但是,如果将弱引用 装箱 (在闭包捕获中发生–值类型将放入堆分配的盒子中)–那么您确实可以对该盒子有强引用。这样做的效果等同于对原始实例的弱引用,您只是看不见了一些额外的间接引用。
实际上,这 正是 在外部闭合弱捕获self而内部闭合“强烈捕获”弱引用的示例中发生的情况。结果是两个闭包都不保留self。