如果我在另一个闭包中有一个闭包,那么在外闭合中使用无主/弱一次就足以避免保留周期吗? 例: foo.aClosure({[unowned self] (allowed: Bool) in if allowed { self.doStuff() self.something.anotherClosure({ (s
例:
foo.aClosure({[unowned self] (allowed: Bool) in if allowed { self.doStuff() self.something.anotherClosure({ (s:String) -> (Void) in self.doSomethingElse(s) }) } })如果你没有在外部闭包中创建对self的强引用(例如,通过执行:guard let strongSelf = self else {return}),则仅在外部闭包的捕获列表中声明弱或无主自我就足以避免保留周期.
如果确实在闭包中创建了一个强引用,则必须将一个捕获列表添加到内部闭包中,以确保它捕获您对弱自身的强引用.
这里有些例子:
import Foundation import PlaygroundSupport class SomeObject { typealias OptionalOuterClosure = ((Int) -> Void)? typealias InnerClosure = () -> Void var outerClosure: OptionalOuterClosure func setup() { // Here are several examples of the outer closure that you can easily switch out below // All of these outer closures contain inner closures that need references to self // optionalChecks // - has a capture list in the outer closure // - uses the safe navigation operator (?) to ensure that self isn't nil // this closure does NOT retain self, so you should not see the #2 calls below let optionalChecks: OptionalOuterClosure = { [weak self] callNumber in print("outerClosure \(callNumber)") self?.delayCaller { [weak self] in print("innerClosure \(callNumber)") self?.doSomething(callNumber: callNumber) } } // copiedSelfWithInnerCaptureList // - has a capture list in the outer closure // - creates a copy of self in the outer closure called strongSelf to ensure that self isn't nil // - has a capture list in the inner closure // - uses the safe navigation operator (?) to ensure strongSelf isn't nil // this closure does NOT retain self, so you should not see the #2 calls below let copiedSelfWithInnerCaptureList: OptionalOuterClosure = { [weak self] callNumber in guard let strongSelf = self else { return } print("outerClosure \(callNumber)") strongSelf.delayCaller { [weak strongSelf] in print("innerClosure \(callNumber)") strongSelf?.doSomething(callNumber: callNumber) } } // copiedSelfWithoutInnerCaptureList // - has a capture list in the outer closure // - creates a copy of self in the outer closure called strongSelf to ensure that self isn't nil // - does NOT have a capture list in the inner closure and does NOT use safe navigation operator // this closure DOES retain self, so you should see the doSomething #2 call below let copiedSelfWithoutInnerCaptureList: OptionalOuterClosure = { [weak self] callNumber in guard let strongSelf = self else { return } print("outerClosure \(callNumber)") strongSelf.delayCaller { print("innerClosure \(callNumber)") strongSelf.doSomething(callNumber: callNumber) } } // retainingOuterClosure // - does NOT have any capture lists // this closure DOES retain self, so you should see the doSomething #2 call below let retainingOuterClosure: OptionalOuterClosure = { callNumber in print("outerClosure \(callNumber)") self.delayCaller { print("innerClosure \(callNumber)") self.doSomething(callNumber: callNumber) } } // Modify which outerClosure you would like to test here outerClosure = copiedSelfWithInnerCaptureList } func doSomething(callNumber: Int) { print("doSomething \(callNumber)") } func delayCaller(closure: @escaping InnerClosure) { delay(seconds: 1, closure: closure) } deinit { print("deinit") } } // Handy delay method copied from: http://alisoftware.github.io/swift/closures/2016/07/25/closure-capture-1/ func delay(seconds: Int, closure: @escaping () -> Void) { let time = DispatchTime.now() + .seconds(seconds) DispatchQueue.main.asyncAfter(deadline: time) { print("