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

时间:2016-08-10 05:02:53

标签: swift swift2 closures

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

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

  

'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
    }
}

在班级init的{​​{1}}中,我通过闭包调用了A。在该闭包中,捕获列表有效。但是当我将闭包声明为属性时(第4 - 7行),捕获列表不起作用。

这是否意味着闭包属性不具有对doStuff的强引用,并且具有隐式self捕获列表?但这对我来说没什么意义......

1 个答案:

答案 0 :(得分:1)

在调用init()方法之前,类/结构属性通常会被初始化,因此在实例正确分配之前。由于此原因,您的媒体资源中的捕获无效,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
}