21628


Swiftで、サーバからのデータをPHP経由でJSON取得して、  
画面上に反映させたいと考えています。

そのためのデータ取得の際、サーバーから取得したJSONの値を  
読み出す部分でエラーが発生していて、困っています。

[code]

        private func setJsonDataListByType(jsonList : NSArray) -> Array<String> {
        var dataList = Array<String>()
        for json in jsonList {
            let data = json["name"] as! String
    
            dataList.append(data)
        }
    
        return dataList
    }
    
[/code]

この、json["name"]の部分で、下記のようなエラーが発生してしまいました。

[code]

    Cannot subscript a value of type 'Element' (aka 'AnyObject') with an index of type 'String'
    
[/code]

昨日までは特に何のエラーも起きていなかった部分なので、  
なぜこんなエラーが発生したのかわかりません。

よろしくお願いします。


CC BY-SA 3.0
2016-01-29T06:26:12.183
21465
2016-02-02T11:15:12.050
14172
question
swift json xcode7
Swift2.0でJSONデータの取得について


まずは、あなたのコードのこの部分をよく確認してください。

[code]

    for json in jsonList {
        let data = json["name"] as! String
    
        dataList.append(data)
    }
    
[/code]

あなたは、`jsonList`をNSArray型と宣言しておられますから、その要素はAnyObject型ということになります。つまりfor-
in文中の`json`は、AnyObject型として宣言されたことになります。  
次の行であなたはそのAnyObject型の`json`に添え字付けをしてアクセスしていますが、Swiftでは、AnyObject型の変数を通じて呼び出せるメソッド(添え字付け`subscript`も特殊なメソッドとして扱われます)は、「Objective-
Cのメソッドだけ」と言う仕様になっています。

この部分には、あまり大きな声では語られていないいくつかの制限事項があって、「少なくともどこか一つのソースファイルで(間接的にでも)importされているフレームワーク内のメソッドしか呼べない」とか、「同名でシグニチャーのことなるメソッドが複数importされている時は、その全てが呼べなくなる」とかいう動作をします。

お判りいただけると思うのですが、あなたの場合は、この後者の制限に引っかかってAnyObjectに対する添え字付けが利用できない状況になっているものと思われます。  
(Appleのdeveloper
forumsですぐに見つかった例ですと、GameKitをimportした際に同じメッセージのエラーが出るようになったという報告があります。その時は、SKNodeのextensionに定義されていた次の添え字付け(subscript)がNSDictionaryとぶつかってしまい、どちらも利用できなくなってしまったという形です。)

[code]

    extension SKNode {  
        public subscript (name: String) -> [SKNode] { get }  
    }  
    
[/code]

このような事態を避けるための一番確実な方法は、「AnyObject型の変数に対して直接メソッド呼び出し(添え字付けを含む)を行わず、AnyObject型の値は必ず適切にキャストしてから用いる」のを徹底することです。

あなたのコードの場合ですと、ついでにDictionaryかどうかのチェックも兼ねて次のように書き換えれば、ご質問中にあるようなエラーは出なくなると思うのですが、お試しいただけますでしょうか。

[code]

    private func setJsonDataListByType(jsonList : NSArray) -> Array<String> {
        var dataList = Array<String>()
        for case let json as [String: String] in jsonList {
            let data = json["name"]!
    
            dataList.append(data)
        }
    
        return dataList
    }
    
[/code]


CC BY-SA 3.0
2016-02-02T11:15:12.050
21628
2016-02-02T11:15:12.050
13972
21465
answer