1

私が通常見る強い参照サイクルの例は、互いに指し示すプロパティを持つ2つのクラスを含みます。一つだけのクラスは、このような他のインスタンスを指しているプロパティを持っている場合は、何を:これは強力なリファレンスサイクルかメモリリークですか?

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をして以来、これは暗黙のうちに行われていますか?

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

+2

コードに漏れも循環参照もありません。 'myClassA'を' nil'に設定すると、ARCは自動的に 'ClassB'の所有権を壊して、両方とも割り当てを解除します。 – ozgur

+0

これを拡張するには、グラフには1つのエッジ( 'myClassA.classB - > myClassB')しかないのでサイクルはありません。 – jtbandes

+0

そのコードがリンクを引き起こした場合、ARCはわずかに役立ちます。インスタンス・レベルで保持されているすべての参照は、インスタンスが解放されると解放されます。 – Avi

答えて

2

@ozgur、@jtbandes、@Avi、および@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 

注意する事もあなたかかわらず、ということです最初にmyClassBnilに設定すると、最初にmyClassAが解放されます。 myClassAが解放されると、myClassBへの最終参照がARCによって解放され、myClassBが解放されます。


ClassBClassAへの強い参照を保持している、強力な基準周期を実証するために:

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プロパティのいずれかをweakと宣言します。どちらあなたが選択したオブジェクトが解放され得ることを順番に影響します。

あなたが宣言するとweak var classB: ClassBClassA中:

出力:代わり場合

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 
関連する問題