1

私がよく目にする強参照サイクルの例には、互いに参照するプロパティを持つ 2 つのクラスが含まれています。ただし、クラスの 1 つだけが、次のように他のインスタンスを指すプロパティを持っている場合はどうなるでしょうか。

class ClassA {
    var classB: ClassB? = nil
}

class ClassB {

}

次に、次のようにインスタンスを作成します。

var myClassA = ClassA()
var myClassB = ClassB() //Reference count 1
myClassA.classB = myClassB //Reference count 2

// Now deallocate
myClassB = nil  //Reference count 1
myClassA = nil

の割り当てを解除myClassBしたので、参照カウントは 1 です。 の参照カウントはどうなりましたmyClassA.classBか? myClassA.classB = nil私はこれをやったことがないか、以前にやったことがないので、ゼロになることはありませんでしたdeinit。私がやったので、これは暗黙のうちに行われmyClassA = nilますか?

これは、強い参照サイクルとして分類できるものですか? 少なくともメモリリークだと思いますが、これは本当ですか?

4

1 に答える 1

2

@ozgur、@jtbandes、@Avi、および @Rob がコメントで説明したように、強い参照サイクルやリークはありません。

Playground で実行できる @Rob のコメントに基づく例を次に示します。

class ClassA {
    var classB: ClassB?

    deinit {
        print("ClassA deallocated")
    }
}

class ClassB {
    deinit {
        print("ClassB deallocated")
    }
}

class Tester {
    func test() {
        var myClassA: ClassA! = ClassA()
        var myClassB: ClassB! = ClassB() //Reference count 1
        myClassA.classB = myClassB //Reference count 2

        // Now deallocate
        print("setting myClassB to nil")
        myClassB = nil  //Reference count 1
        print("setting myClassA to nil")
        myClassA = nil
        print("all done")
    }
}

// Create `Tester` object and call `test`:

Tester().test()

出力:

setting myClassB to nil
setting myClassA to nil
ClassA deallocated
ClassB deallocated
all done

注意すべきことは、最初に設定myClassBしても、それが最初に解放されるということです。が解放されると、 への最終参照がARC によって解放されてから解放されます。nilmyClassAmyClassAmyClassBmyClassB


強い参照サイクルを実証するには、次ClassBへの強い参照を保持しますClassA

class ClassA {
    var classB: ClassB?

    deinit {
        print("ClassA deallocated")
    }
}

class ClassB {
    var classA: ClassA?

    deinit {
        print("ClassB deallocated")
    }
}

class Tester {
    func test() {
        var myClassA:ClassA! = ClassA()
        var myClassB:ClassB! = ClassB() //Reference count 1
        myClassA.classB = myClassB //Reference count 2
        myClassB.classA = myClassA

        // Now deallocate
        print("setting myClassB to nil")
        myClassB = nil  //Reference count 1
        print("setting myClassA to nil")
        myClassA = nil
        print("all done")
    }
}

Tester().test()

出力:

setting myClassB to nil
setting myClassA to nil
all done

どちらのオブジェクトにも他方への強い参照が含まれている場合、どちらのオブジェクトも割り当て解除されません。この強い参照サイクルを断ち切るには、classBまたはclassAプロパティの 1 つを に宣言しますweak。どちらを選択するかは、オブジェクトが解放される順序に影響します。

weak var classB: ClassBで宣言した場合ClassA:

出力:

setting myClassB to nil
ClassB deallocated
setting myClassA to nil
ClassA deallocated
all done

代わりに、次のように宣言しweak var classA: ClassA in ClassBます。

出力:

setting myClassB to nil
setting myClassA to nil
ClassA deallocated
ClassB deallocated
all done
于 2016-05-22T12:43:51.850 に答える