Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Swift 当传递方法而不是闭包时,将发生Retain循环_Swift_Memory Management_Closures_Retain Cycle - Fatal编程技术网

Swift 当传递方法而不是闭包时,将发生Retain循环

Swift 当传递方法而不是闭包时,将发生Retain循环,swift,memory-management,closures,retain-cycle,Swift,Memory Management,Closures,Retain Cycle,在Swift中,我们可以使用ObjC中没有的特性:可以在任何需要使用闭包的地方使用方法。但它会导致循环。看看这个例子: import Foundation class C1 { let closure: Void -> Void init(closure: Void -> Void) { self.closure = closure } deinit { print("C1 deinit") } } cla

在Swift中,我们可以使用ObjC中没有的特性:可以在任何需要使用闭包的地方使用方法。但它会导致循环。看看这个例子:

import Foundation

class C1 {
    let closure: Void -> Void
    init(closure: Void -> Void) {
        self.closure = closure
    }

    deinit {
        print("C1 deinit")
    }
}

class C2 {
    var c1: C1!

    func initializeC1() {
        c1 = C1(closure: f)
    }

    func f() {}

    deinit {
        print("C2 deinit")
    }
}

func main() {
    let c2 = C2()
    c2.initializeC1()
}

main()
这里我们创建了循环C2->C1->f->C2。如果运行此程序,
deinit
将不会被调用。但是如果您将
initializeC1
中的
f
替换为
{}
,例如,它将是

对于常规闭包,我们可以使用捕获列表来避免强保留,但看起来您不能将它们用于方法。 因此,问题是:在这种情况下,我们如何打破保留循环,这是可能的吗?

当然,我们可以通过将绑定方法包装成闭包来“弱化”它:

import Foundation

class C1 {
    let closure: Void -> Void
    init(closure: Void -> Void) {
        self.closure = closure
    }

    deinit {
        print("C1 deinit")
    }
}

class C2 {
    var c1: C1!

    func initializeC1() {
        // HERE we wrap a method call into a closure to break retain-cycle.
        c1 = C1(closure: { [weak weakSelf = self] in
            weakSelf?.f()
        })
    }

    func f() {}

    deinit {
        print("C2 deinit")
    }
}

func main() {
    let c2 = C2()
    c2.initializeC1()
}

main()
//C2 deinit
//C1 deinit

很好的回答,但是我们又回到了闭包语法,这是我试图避免的。如果没有更好的解决方案,它将被接受。我在文档中没有看到明确的声明,但在Swift中方法似乎与它们的实例紧密相连,我们无法改变这种行为。我也不认为有什么方法可以使一个漂亮的实用程序克服这个限制。我想你会感兴趣的: