在阅读了苹果的一些文章和开发者指南后,我仍然对closure中的捕获列表感到困惑。“捕获”是什么意思,它是如何在无主自我和弱小自我的幕后工作的?闭包如何在不拥有对象的情况下使用self?我认为这就像是复制了一个对象,所以当它完成时,它会像值类型一样从堆栈中传递出来,但我想我错了。我希望这里有人能让我更容易和清晰地理解它,或者把我链接到一篇回答这个特定问题的好文章上。感谢你的预支
发布于 2018-05-02 15:44:40
我的理解是,它是关于所有权和持有对象的,这意味着只要我们声明对象的所有权,它就不能从内存中释放,即使代码的另一部分将其设置为nil或类似的。
对于weak,我们说销毁对象是可以的,只有当它还在的时候我们才会使用它。
因此,当在闭包中将self声明为weak时,我们会说,如果self仍然存在,那么在执行闭包的时候,我们通常会这样做,否则闭包将被静默忽略,不会产生错误。
发布于 2018-05-02 15:45:27
这主要与reference counting有关。在闭包内部使用的任何实例(但在外部声明)都是强引用的(即它的引用计数是递增的)。这可能导致保留周期,例如
class MyClass {
var myClosure: (() -> Void)!
init() {
myClosure = {
self.foo()
}
}
func foo() {
}
}在上面的示例中,MyClass的实例保留了对myClosure的引用,反之亦然,这意味着MyClass实例将永远留在内存中。
您还可以有更复杂/更难发现的保留周期,所以您需要真正注意,如果您有任何疑问,请向您的类的deinit方法添加一些print调用,以确保(或使用工具)。
为了避免这些问题,您可以将在闭包中捕获的对象标记为unowned或weak。这意味着它们的引用计数不会增加,您可以避免这些保留周期。上面的示例可以通过以下两种方式完成:
myClosure = { [weak self] in
self?.foo()
}或者,对于这个例子,更好的方法是这样:
myClosure = { [unowned self] in
self.foo()
}虽然第一种方法总是安全的,而且您更有可能这样做,但在本例中很容易推断出unowned版本,因为您知道myClosure不会比self存活时间更长。但是,如果您不能100%确定self是否总是比闭包存在时间更长,请使用weak。
还请注意,您可以标记如何捕获闭包中使用的多个对象,只需用逗号将其分隔,例如
myClosure = { [weak self, unowned bar] in
self?.foo(bar)
}发布于 2020-09-16 12:40:06
如果我们记住,默认情况下,捕获的值是闭包中的强引用,我们可以假设这会创建保留周期(坏东西)。
捕获列表是可以传递到闭包中的变量数组。捕获列表的目的是更改传入的变量的强度。这是用来打破保留周期。
例如:
// strong reference
[label = self.myLabel!] in
// weak reference
[weak label = self.myLabel!] in
// unowned reference
[unowned self] inhttps://stackoverflow.com/questions/50129147
复制相似问题