在另一个闭包中调用快速闭包导致的堆栈溢出

han*_*bao 5 stack-overflow macos closures ios swift

更新:此错误已由rdar:// 20931915确认,并已在Xcode 7 beta 3中修复。


我发现了一个奇怪的错误,该错误是由于在调试版本的另一个闭包中调用快速闭包引起的。我的Xcode是6.3.1版和Swift 1.2版。这是代码:

import Swift

class ClosureStackOverflow {
    private var b: Bool = false
    private func callClosure1(callback: Void -> Void) {
        println("in closure 1")
        callback()
    }

    private func callClosure2(callback: Void -> Void) {
        println("in closure 2")
        callback()
    }

    func call() {
        callClosure1 { [weak self] in
            self?.callClosure2 {
                self?.b = true
            }
        }
    }
}

let c = ClosureStackOverflow()
c.call()
Run Code Online (Sandbox Code Playgroud)

上面的代码可以很好地编译。但是,如果调用其call()方法,它将无限打印“ inclosure 2”,并最终使堆栈溢出。

您能解释一下为什么在另一个闭包中调用该闭包会导致此错误吗?

谢谢。

Leo*_*Leo 2

将您的代码更改为此,它将起作用

    class ClosureStackOverflow {
    private var b: Bool = false
    private func callClosure1(callback: Void -> Void) {
        println("in closure 1")
        callback()
    }

    private func callClosure2(callback: Void -> Void) {
        println("in closure 2")

        callback()
    }

    func call() {
        callClosure1 {
            self.callClosure2 {
                self.b = true
            }
        }
    }
    deinit{
        print("deinit")
    }
}
Run Code Online (Sandbox Code Playgroud)

看来你[weak self] in在函数中声明了,它导致了问题。

我也测试这个来调用

 let c = ClosureStackOverflow()
    c.call()
Run Code Online (Sandbox Code Playgroud)

它将输出

 in closure 1
in closure 2
deinit
Run Code Online (Sandbox Code Playgroud)

看来不使用weak self不会造成循环引用

此外 我还测试将功能更改为此

  func call() {
    callClosure1 {
        [weak self] in
        self!.callClosure2 {
            self?.b = true
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

它也会起作用。所以我认为这可能是 swift 的一些编译器错误。