在我的代码中,我调用了一些采用闭包的方法。我每次都通过相同的关闭。所以我决定将闭包提取为属性。每次调用方法时都传递该属性。这可以大大减少重复代码。
但是,当我尝试将捕获列表[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
捕获列表?但这对我来说没什么意义......
答案 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
}