内部闭包的捕获列表是否需要将`self`重新声明为"weak"或"unowned"? [英] Do capture lists of inner closures need to redeclare `self` as `weak` or `unowned`?

查看:102
本文介绍了内部闭包的捕获列表是否需要将`self`重新声明为"weak"或"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从未被调用,并且deinitanotherFunctionWithTrailingClosure调用其闭包之前被调用.

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆