22288

[code]

    class Testdata: NSObject {
        dynamic var data1 = Data1()
    
        var updateDate: NSDate = NSDate()
    
        class Data1: NSObject {
            dynamic private(set) var version: [NSNumber] = []
            // unsignedChar配列として初期化しておく
        }
    }
    
[/code]

上記のような場合、以下のようにforKeyPathに配列を渡すことはできませんでした。  
setValue(value: AnyObject?, forKeyPath: String)  
配列に対しては使用できないのでしょうか。

[code]

    let testdataobj = Testdata()
    testdataobj.setValue(0x20, forKeyPath: "data1.version[0]")
    
[/code]


CC BY-SA 3.0
2016-02-19T12:42:44.143
22275
2016-02-19T22:11:46.030
12842
question
swift
setValue()は配列で使用できないのでしょうか


結論だけから言うと`setValue(_:forKeyPath:)`や`valueForKeyPath(_:)`で配列の要素を参照したり変更したりはできません。

他言語の似たような仕組みを知っていると「あれっ？」と思うのですが、設計思想が違うんで仕方ないといったところでしょうか。

[code]

    class Testdata: NSObject {
        dynamic var data1 = Data1()
    
        class Data1: NSObject {
            //元の配列に十分なサイズがないとアクセスできません
            dynamic private(set) var version: [NSNumber] = [2,4,6]
        }
    }
    let testdataobj = Testdata()
    //他言語なら当然サポートしてくれていそうなこの構文はサポートしていない
    //testdataobj.setValue(0x20, forKeyPath: "data1.version[0]") //->クラッシュ
    
[/code]

KVCを使って配列の要素を変更するときは、こんなメソッドを使う必要があります。

[code]

    testdataobj.mutableArrayValueForKeyPath("data1.version")[0] = 0x20
    print(testdataobj.data1.version[0]) //->32
    
[/code]

mutableArrayValueForKeyPath(_:)の戻り値の型はNSMutableArrayなのですが、その実体は

[code]

    print(testdataobj.mutableArrayValueForKeyPath("data1.version").dynamicType)
    //->NSKeyValueSlowMutableArray
    
[/code]

てな感じの内部クラスなので、別スレッドであったような更新時間の監視目的でオーバライドするのは難しいでしょう。

なかなか気難しいKVCなのですが、一方でコレクション演算子なんてものがあり、こんなことができたりします。

[code]

    testdataobj.valueForKeyPath("data1.version.@sum.self") //32+4+6
    testdataobj.valueForKeyPath("data1.version.@count") //3
    
[/code]

このあたり前にあげた[KVCの公式ドキュメント](https://developer.apple.com/jp/documentation/KeyValueCoding.pdf)をよく読めば…と書きたいところですが、私自身はよく読んでもわからずシンプルなコード例を作るのにさんざんPlayground上で実行時エラーを出してしまいました。  
Core Dataなどを活用する場合にも必要になってきますので、オンラインの他のリソースを合わせて参照しながら必要に応じて試しながら調べてみてください。


CC BY-SA 3.0
2016-02-19T22:11:46.030
22288
2016-02-19T22:11:46.030
13972
22275
answer