3

ここに、閉鎖の強い参照サイクルの例をいくつか示します。格納されたプロパティにクロージャーを割り当てると、クロージャー キャプチャ リストを使用して、キャプチャされた参照を非所有/弱にすることができます。しかし、格納されたプロパティ クロージャにメソッドを割り当てたり、外部スコープのクロージャにメソッドを割り当てたりすると、キャプチャ リストを使用できません。

最後の 2 つのケースで参照サイクルを削除するにはどうすればよいですか?

クロージャのみのキャプチャ リストで強い参照サイクルを作成して回避する例

internal class ClosureClass {
    internal let p1: String
    internal lazy var p2: () -> String = {
        [unowned self] // if you comment this out there is a strong reference cycle
        () -> String in
        return self.p1
    }

    internal init() {
        self.p1 = "Default value of ClosureClass"
    }

    deinit {
        print("Object with property '\(self.p1)' is being deinitialized")
    }
}
print("Test 'Closure with strong reference to self':")
var cc: ClosureClass? = ClosureClass.init()
cc!.p2() // lazy need to call it once, else it will not be initiliazed
cc = nil

メソッドからのクロージャーで強い参照サイクルを作成する例

internal class MethodToClosureClass {

    internal let p1: String
    internal lazy var p2: () -> String = method(self) // Why not self.method ? Will create a strong reference cycle, but I can not set the reference to weak or unowned like in closures with the closure capture list

    internal init() {
        self.p1 = "Default value of MethodToClosureClass"
    }

    internal func method() -> String {
        //      [unowned self] in
        return self.p1
    }

    deinit {
        print("Object with property '\(self.p1)' is being deinitialized")
    }
}
print("Test 'Set closure with method intern':")
var m2cc: MethodToClosureClass? = MethodToClosureClass.init()
m2cc!.p2() // lazy need to call it once, else it will not be initiliazed
m2cc = nil

メソッドからクロージャをexternから設定して強参照サイクルを作成する例

internal class MethodClass {
    internal let p1: String
    internal var p2: () -> String = {
        return ""
    }

    internal init() {
        self.p1 = "Default value of MethodClass"
    }

    internal func method() -> String {
        //      [unowned self] in
        return self.p1
    }

    deinit {
        print("Object with property '\(self.p1)' is being deinitialized")
    }
}
print("Test 'Set closure with method extern':")
var mc: MethodClass? = MethodClass.init()
var method: () -> String = mc!.method // will create a strong reference
mc!.p2 = method
mc = nil

出力

「自己への強い参照による閉鎖」をテストします。

プロパティ「ClosureClass のデフォルト値」を持つオブジェクトが初期化解除されています

「メソッド intern でクロージャを設定」をテストします。

「extern メソッドでクロージャを設定」をテストします。

4

1 に答える 1