为什么无法将捕获列表添加到闭包属性?



在我的代码中,我调用了一些接受闭包的方法。我每次传递的都是相同的闭包。所以我决定提取闭包作为一个属性。并在每次调用功能时传递那个属性。这可以大大减少重复的代码。

然而,当我试图将捕获列表[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
    }
}

A类的init中,我用闭包调用doStuff。在该闭包中,捕获列表可以工作。但是当我将闭包声明为属性(第4 - 7行)时,捕获列表不起作用。

这是否意味着闭包属性不包含对self的强引用,并且有一个隐式的[unowned self]捕获列表?

类/结构属性通常在 init()方法被调用之前被初始化,因此在实例被正确分配之前。属性中的捕获是无效的,因为self还没有初始化。

你可以通过惰性初始化属性来使它工作:

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

这可以工作,因为惰性属性只能在self完全初始化时才能访问。

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

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

最新更新