24550


こんにちは、ちょっと混乱してきたので質問させてください。  
あるアプリを作ってる際に以下が気になりました。

[code]

    //
    //  WordListVCL.swift
    //  FinalStudyEnglish
    //
    //
    
    import UIKit
    #if !RX_NO_MODULE
    import RxSwift
    import RxCocoa
    #endif
    
    class WordListVCL: EnglishBase,ListDataSourceDelegate,UITableViewDelegate,ListProtocol {
    
        let datasource = WordDataSource()
    
        var aryWord: Variable<Array<NSMutableArray>> = Variable(Array<NSMutableArray>())
        var aryDate: Array<String> = Array<String>()
    
        func initData(){
            let data = EnglishWord.singleton.getWordWithLimit(intCategoryId, intStart: intStart, intLimit: intLimit)
            aryDate = data.0
            datasource.aryWordSections = aryDate
    
            aryWord.value = data.1
            print(aryWord.value)
            print(aryDate)
    
        }
    }
    
    //
    //  WordDataSource.swift
    //  FinalStudyEnglish
    //
    //
    
    import UIKit
    
    class WordDataSource: ListDataSource {
        weak var aryWordSections: NSArray?
    }
    
[/code]

ある強参照の変数を弱参照の変数に代入すると、代入した瞬間に空のようです。  
自分のstrongとweakのイメージとして、例えば、「A」というクラスでstrongで確保してる変数は、  
「B」というクラスの変数に代入する際には、その代入される側はweakまたはunownedが望ましいと理解してるのですが、違うのでしょうか？


CC BY-SA 3.0
2016-05-04T00:35:04.683
24545
2016-05-04T05:13:41.730
2016-05-04T05:13:41.730
5519
403
question
swift objective-c
Swiftのstrong, weak


> 自分のstrongとweakのイメージとして、例えば、「A」というクラスでstrongで確保してる変数は、  
>  「B」というクラスの変数に代入する際には、その代入される側はweakまたはunownedが望ましいと理解してるのですが、違うのでしょうか

リファレンスカウントで気をつけなければならないことは循環参照です。  
上記の例では単に参照カウントが増えるだけで循環しないので問題ありません。

最初はAとBの両方から強く参照されているので参照カウントは2です。AまたはBが解放されるとカウントが1減ります。さらに残ったどちらかが解放されるとカウントがゼロになり無事にその変数も解放されます。

循環参照とは、AがBをインスタンス変数として強く保持していて、かつ、BもAをインスタンス変数として強く保持している、という状態です。  
この場合、AとBはお互いに強く参照しているので、参照カウントは両方とも1です。そして、そのカウントは減ることがないので、メモリは解放されることがなく、メモリリークが発生します。

デリゲートで弱参照が使用されるのは、仕組み上、必然的に参照を循環させるからです。デリゲート元がデリゲート先を通常は強参照で保持しているので、デリゲート先でさらにデリゲート元を強参照してしまうと循環参照になります。  
ですので、普通はライフサイクルが短いデリゲート先が弱参照としてデリゲートを保持します。そうすることでデリゲート元を解放することができます。

デリゲートパターン以外の例でいうと、ブロックまたはクロージャによって`self`がキャプチャされることで循環参照が起こる場合があります。  
ブロックをメソッドスコープを超えて保持するとき、そのブロックが`self`をキャプチャすると、ブロックは`self`に強参照されていて、ブロックは`self`を強参照している、という状態になるので、循環参照が起こります。

詳しくは下記のドキュメントや書籍をご覧になるのが良いと思います。

[高度なメモリ管理プログラミングガイド](https://developer.apple.com/jp/documentation/MemoryMgmt.pdf)  
[エキスパートObjective-Cプログラミング ― iOS/OS Xのメモリ管理とマルチスレッド](http://tatsu-
zine.com/books/objc)


CC BY-SA 3.0
2016-05-04T05:11:56.330
24550
2016-05-04T05:11:56.330
5519
24545
answer