我经常这样做,
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()
}
}
或者, this
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()
}
}
所有三个建议似乎才能完美运作。这里意义的深度是什么?一个人应该做什么?强引用弱引用,弱引用还是强引用?生存还是毁灭?这是个问题!
答案 0 :(得分:88)
首先,请注意,您通常不需要担心DispatchQueue.main.asyncAfter
的保留周期,因为闭包将在某些点执行。因此,无论您是否轻微捕获self
,您都不会创建永久保留周期(假设tickle.fresh
也没有)。
是否在外部[weak self]
闭包上放置asyncAfter
捕获列表完全取决于您是否希望在调用闭包之前保留self
(在您设置的时间之后) )。如果您在调用关闭之前不需要self
保持活着,请将[weak self]
放入,如果您这样做,则不要将其放入。
你是否在内部闭包上放置[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
示例完全相同)。
但是,如果弱引用是盒装(这种情况发生在闭包捕获 - 值类型将被放入堆分配的盒子中) - 那么你确实可以对该盒子有一个强引用。这种效果相当于对原始实例的弱引用,你只需要一个不可见的额外间接位。
实际上,这是完全在外部闭包弱捕获self
并且内部闭合强烈捕获'的示例中发生的情况。那个弱的参考。结果是两个闭包都没有保留self
。