首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Swift - Capture列表自我澄清

Swift - Capture列表自我澄清
EN

Stack Overflow用户
提问于 2018-05-02 15:22:40
回答 3查看 377关注 0票数 1

在阅读了苹果的一些文章和开发者指南后,我仍然对closure中的捕获列表感到困惑。“捕获”是什么意思,它是如何在无主自我和弱小自我的幕后工作的?闭包如何在不拥有对象的情况下使用self?我认为这就像是复制了一个对象,所以当它完成时,它会像值类型一样从堆栈中传递出来,但我想我错了。我希望这里有人能让我更容易和清晰地理解它,或者把我链接到一篇回答这个特定问题的好文章上。感谢你的预支

EN

回答 3

Stack Overflow用户

发布于 2018-05-02 15:44:40

我的理解是,它是关于所有权和持有对象的,这意味着只要我们声明对象的所有权,它就不能从内存中释放,即使代码的另一部分将其设置为nil或类似的。

对于weak,我们说销毁对象是可以的,只有当它还在的时候我们才会使用它。

因此,当在闭包中将self声明为weak时,我们会说,如果self仍然存在,那么在执行闭包的时候,我们通常会这样做,否则闭包将被静默忽略,不会产生错误。

票数 1
EN

Stack Overflow用户

发布于 2018-05-02 15:45:27

这主要与reference counting有关。在闭包内部使用的任何实例(但在外部声明)都是强引用的(即它的引用计数是递增的)。这可能导致保留周期,例如

代码语言:javascript
复制
class MyClass {
    var myClosure: (() -> Void)!

    init() {
        myClosure = {
            self.foo()
        }
    }

    func foo() {
    }
}

在上面的示例中,MyClass的实例保留了对myClosure的引用,反之亦然,这意味着MyClass实例将永远留在内存中。

您还可以有更复杂/更难发现的保留周期,所以您需要真正注意,如果您有任何疑问,请向您的类的deinit方法添加一些print调用,以确保(或使用工具)。

为了避免这些问题,您可以将在闭包中捕获的对象标记为unownedweak。这意味着它们的引用计数不会增加,您可以避免这些保留周期。上面的示例可以通过以下两种方式完成:

代码语言:javascript
复制
myClosure = { [weak self] in
    self?.foo()
}

或者,对于这个例子,更好的方法是这样:

代码语言:javascript
复制
myClosure = { [unowned self] in
    self.foo()
}

虽然第一种方法总是安全的,而且您更有可能这样做,但在本例中很容易推断出unowned版本,因为您知道myClosure不会比self存活时间更长。但是,如果您不能100%确定self是否总是比闭包存在时间更长,请使用weak

还请注意,您可以标记如何捕获闭包中使用的多个对象,只需用逗号将其分隔,例如

代码语言:javascript
复制
myClosure = { [weak self, unowned bar] in
    self?.foo(bar)
}
票数 1
EN

Stack Overflow用户

发布于 2020-09-16 12:40:06

如果我们记住,默认情况下,捕获的值是闭包中的强引用,我们可以假设这会创建保留周期(坏东西)。

捕获列表是可以传递到闭包中的变量数组。捕获列表的目的是更改传入的变量的强度。这是用来打破保留周期。

例如:

代码语言:javascript
复制
// strong reference
[label = self.myLabel!] in

// weak reference
[weak label = self.myLabel!] in

// unowned reference
[unowned self] in
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/50129147

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档