43709


いつもお世話になっております。

複数のインスタンスを配列で管理し、その配列を別クラスで管理したいと考えてます。  
循環参照になってしまい解放されない状況になってしまいました。  
どのように配列をweakさせれば良いでしょうか？

よろしくお願い致します。

サンプルコード

[code]

    class Human {
        init() {}
        deinit { print("deinit Human") }
    }
    class Home {
        var family: [Human?]?  // weakしたい
        init() {}
        deinit { print("deinit Home") }
    }
    var humanA: Human? = Human()
    var humanB: Human? = Human()
    var home: Home? = Home()
    home!.family = [humanA!, humanB!]
    humanA = nil  // deinitされない
    
[/code]


CC BY-SA 3.0
2018-05-01T22:58:42.810
43708
2018-05-02T06:15:43.850
20142
question
swift4
インスタンスを格納した配列をweak化するには


これは循環参照ではなく、一つのインスタンスがhumanAとhome!.family[0]に代入されている(共有されている)状態です。  
`humanA = nil`  
だけでなく、  
`home!.family.remove(at: 0)`  
等の方法で、familyの方に代入されているインスタンスも削除する必要があります。


CC BY-SA 3.0
2018-05-01T23:58:12.567
43709
2018-05-01T23:58:12.567
8077
43708
answer


サンプルコードでは、`Human`インスタンスが、`Home`インスタンスを参照し、`Home`インスタンスが`Human`インスタンスを参照する構造になっていないので、循環参照は起きていません。  
Playgroundで実行した場合に、インスタンスが解放されない結果になっているのでしょうか？でしたら、サンプルコードの実行部分を、下のように、`do
{}`で囲んでみてください。

[code]

    class Human {
        init() {}
        deinit { print("deinit Human") }
    }
    class Home {
        var family: [Human?]?
        init() {}
        deinit { print("deinit Home") }
    }
    
    do {
        var humanA: Human? = Human()
        var humanB: Human? = Human()
        var home: Home? = Home()
        home!.family = [humanA!, humanB!]
        // humanA = nil  // あってもなくてもかまわない。
    }
    
[/code]

> deinit Home  
>  deinit Human  
>  deinit Human

このような出力になります。`do`文を使って、スコープの終わりを明示することで、インスタンスが解放されるタイミングを与えていると推理できます。Playgroundでなく、アプリケーション開発などの、実践的なコード記述では、`if`文、`for`文、関数、メソッドの実装など、かならずスコープの中でコードが書かれますから、インスタンスが解放されないことはないと考えていいでしょう。


CC BY-SA 4.0
2018-05-02T06:15:43.850
43723
2018-05-02T06:15:43.850
18540
43708
answer