内部闭包的捕获列表是否需要将`self`重新声明为"weak"或"unowned"? [英] Do capture lists of inner closures need to redeclare `self` as `weak` or `unowned`?
问题描述
如果我将闭包传递给了这样的函数:
If I have a closure passed to a function like this:
someFunctionWithTrailingClosure { [weak self] in
anotherFunctionWithTrailingClosure { [weak self] in
self?.doSomething()
}
}
如果我在someFunctionWithTrailingClosure
的捕获列表中将self声明为[weak self]
,而又没有在anotherFunctionWithTrailingClosure
self
的捕获列表中再次将其声明为weak
,则它已经变成了Optional
类型,但是它也是也成为weak
参考?
If I declare self as [weak self]
in someFunctionWithTrailingClosure
's capture list without redeclaring it as weak
again in the capture list of anotherFunctionWithTrailingClosure
self
is already becoming an Optional
type but is it also becoming a weak
reference as well?
谢谢!
推荐答案
不需要anotherFunctionWithTrailingClosure
中的[weak self]
.
您可以凭经验进行测试:
You can empirically test this:
class Experiment {
func someFunctionWithTrailingClosure(closure: () -> ()) {
print("starting someFunctionWithTrailingClosure")
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, Int64(1 * Double(NSEC_PER_SEC))), dispatch_get_main_queue()) {
closure()
print("finishing someFunctionWithTrailingClosure")
}
}
func anotherFunctionWithTrailingClosure(closure: () -> ()) {
print("starting anotherFunctionWithTrailingClosure")
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, Int64(1 * Double(NSEC_PER_SEC))), dispatch_get_main_queue()) {
closure()
print("finishing anotherFunctionWithTrailingClosure")
}
}
func doSomething() {
print("doSomething")
}
func testCompletionHandlers() {
someFunctionWithTrailingClosure { [weak self] in
self?.anotherFunctionWithTrailingClosure { // [weak self] in
self?.doSomething()
}
}
}
// go ahead and add `deinit`, so I can see when this is deallocated
deinit {
print("deinit")
}
}
然后:
func performExperiment() {
dispatch_async(dispatch_get_global_queue(QOS_CLASS_UTILITY, 0)) {
let obj = Experiment()
obj.testCompletionHandlers()
// sleep long enough for `anotherFunctionWithTrailingClosure` to start, but not yet call its completion handler
NSThread.sleepForTimeInterval(1.5)
}
}
如果执行此操作,将会看到doSomething
从未被调用,并且deinit
在anotherFunctionWithTrailingClosure
调用其闭包之前被调用.
If you do this, you'll see that doSomething
is never called and that deinit
is called before anotherFunctionWithTrailingClosure
calls its closure.
已经验证了此行为,我个人仍然倾向于在anotherFunctionWithTrailingClosure
上使用[weak self]
语法使我的意图明确,因为所有这些远非显而易见.
Having verified this behavior, I'd personally still be inclined to use the [weak self]
syntax on anotherFunctionWithTrailingClosure
to make my intent explicit, as all of this is far from obvious.
这篇关于内部闭包的捕获列表是否需要将`self`重新声明为"weak"或"unowned"?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!