为什么我不能将捕获列表添加到闭包 属性?

Why can't I add a capture list to a closure property?

在我的代码中,我调用了一些采用闭包的方法。我每次都通过完全相同的闭包。所以我决定将闭包提取为 属性。并在我每次调用这些方法时传递 属性。这样可以大大减少重复代码。

但是,当我尝试将捕获列表 [weak self] 添加到闭包 属性 时,编译器不允许我这样做!

'weak' may only be applied to class and class-bound protocol types, not '<<error type>>'

我不知道那是什么意思。

MCVE:

class A {
    var num = 0

    let closure: (Int) -> Void = {
        [weak self] x in
        self?.num += x
    }

    init() {
        let b = B()
        b.doStuff {
        [weak self] x in
            self?.num += x
        }
    }


}

class B {
    var stuff: ((Int) -> Void)!

    func doStuff(stuff: (Int) -> Void) {
        self.stuff = stuff
    }
}

在classAinit中,我用闭包调用了doStuff。在该闭包中,捕获列表起作用。但是当我将闭包声明为 属性(第 4 - 7 行)时,捕获列表不起作用。

这是否意味着闭包属性不持有对 self 的强引用并且具有隐式 [unowned self] 捕获列表?但这对我来说意义不大...

Class/Struct 属性通常在 before init() 方法被调用之前初始化,因此 before 实例是适当分配。因此,属性 中的捕获无效,self 尚未初始化。

你仍然可以通过延迟初始化 属性:

lazy var closure: (Int) -> Void = {
    [weak self] x in
    self?.num += x
}

这是有效的,因为惰性属性只能在 self 完全初始化时才能访问。

目前不可能有一个恒定的惰性 属性,但这可能会在未来改变。我知道的唯一解决方法是使用私有 setter:

private(set) lazy var closure: (Int) -> Void = {
    [weak self] x in
    self?.num += x
}