一尘不染

内部闭包的捕获列表是否需要将“ self”重新声明为“ weak”或“ unowned”?

swift

如果我有一个闭包传递给这样的函数:

 someFunctionWithTrailingClosure { [weak self] in
     anotherFunctionWithTrailingClosure { [weak self] in 
         self?.doSomething()
     }
 }

如果我[weak self]someFunctionWithTrailingClosure的捕获列表中声明self为,而没有weak在的捕获列表中再次声明自身,则它anotherFunctionWithTrailingClosure
self已经成为一种Optional类型,但它也同样成为weak引用吗?

谢谢!


阅读 329

收藏
2020-07-07

共1个答案

一尘不染

[weak self]anotherFunctionWithTrailingClosure是没有必要的。

您可以凭经验进行测试:

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调用其闭包之前被调用。

验证了此行为后,我个人仍然倾向于使用[weak self]语法anotherFunctionWithTrailingClosure使我的意图明确,因为所有这些远非显而易见。

2020-07-07