2016-05-15 5 views
0

私はFacebookのSDKグラフリクエストを作成してユーザーの好きなものを得ることができますが、返された値を取得してキーの1つを文字列の配列に格納することに問題があります。要求はキー/値のNSDictionaryを返します。次に、objectForKeyを使用して、私が望むものを返すdataキーを得ることができます:Facebookの "好きな"ページのIDと名前。下付き文字のあいまいな使用ですか?

データは次のように要素を返します。

{ 
     id = 486379781543416; 
     name = "Star Wars Movies"; 
    }, 

私は特に、これらのオブジェクトのすべての唯一の「名前」をしたいと配列[String]にそれらをスローします。私はオブジェクトをループしようとしましたが、エラーが発生していますambiguous use of subscript

request.startWithCompletionHandler{(connection:FBSDKGraphRequestConnection!, result:AnyObject!, error:NSError!) -> Void in 
      let resultdict = result as! NSDictionary  
      let likes = resultdict.objectForKey("data") as! NSArray 
      print("Found \(likes.count) likes") 
      print(likes) 

      for object in likes{ 

       let name = object["name"] as! String //error: ambiguous use of subsript 
       print(name) 
      } 

     } 

それはNSArrayのである問題のように見えるいくつかの研究を行った後とすることを私が代わりにスウィフトのデータ型を使用する必要があります。ここでは、関連するコードです。私はそれをSwift配列にキャストしようとしましたが、違うエラーがあります。

このエラーを処理する最適な方法は何ですか?

ありがとうございます!

更新:ここではどのようなFacebookのAPIリクエストが返すです:可能な限り、あなたは常にNSArrayNSDictionaryとしてネイティブスウィフトコレクション型を使用する必要があります

{ 
    data =  (
       { 
      id = 111276025563005; 
      name = "Star Wars (film)"; 
     }, 
       { 
      id = 115061321839188; 
      name = "Return of the Jedi"; 
     } 
    ); 
    paging =  { 
     cursors =   { 
      after = MTE1MDYxMzIxODM5MTg4; 
      before = Mjc0NzYzODk2MTg4NjY5; 
     }; 
     next = "https://graph.facebook.com/v2.5/10155262562690368/likes?access_token=<redacted>"; 
    }; 
} 

答えて

1

本当に-inspecificを入力しているので、簡単に「あいまいなトリガすることができます添え字 "エラーの使用。

間違った形式のデータを受け取った場合や、まったくデータがない場合は、強制的に強制的に強制的にダウンキャストしないようにしてください。この状況は、クラッシュを防止するために、guardでより優雅に処理されます。あなたのプログラムが強制的にダウンカスケードに成功し、したがってにクラッシュさせる場合、問題のデバッグを支援するためにをという記述のあるエラーメッセージでいつでも呼び出すことができます。

データ構造が正しく理解されている場合、要求はAnyObjectで、[String:AnyObject](任意のオブジェクトに対応する文字列の辞書)になります。 "data"キーの場合、AnyObjectの値は[[String:AnyObject]](任意のオブジェクトに対する文字列の辞書の配列)です。

したがって、キャストを2段階で行う必要があります。まず、resultの条件付きダウンキャストを使用して、[String:AnyObject]としてキャストします。これが失敗すると、ガードのelse節が実行され、コードが戻ります。次に、"data"の値(あなたの「お好み」の配列)を取り出し、条件付きで[[String:AnyObject]]にダウンキャストします。これらの両方の文は、resultDictまたはresultDict["data"]の可能性を扱います。nilです。

guard let resultDict = result as? [String:AnyObject] else {return} 
guard let likes = resultDict["data"] as? [[String:AnyObject]] else {return} 

あなたは結果の辞書が存在しないケースを処理するために、これらのステートメントのかっこ内に好きなエラー処理ロジック置くことができますが、間違ってフォーマットした、または「好き」の配列はありませんでしたその中に。

flatMapを使用して「like」の名前の配列を取得できます。

let likeNames = likes.flatMap{$0["name"] as? String} 

これは、各辞書のような名前の配列を作成します - のような名前が存在しないか、文字列でないならば、それらは追加されません。コンパイラはの特定のを知っているので、likes[[String:AnyObject]]です。要素に添字を付けるにはあいまいさはありません。

あなたの質問のようにより一般的なアプローチが必要な場合は、forループ内でguardステートメントを使用できます。

for object in likes { 
    guard let name = object["name"] as? String else {continue} 
    print(name) 
} 

また、ガードの角括弧内の任意のエラー処理を行うことができます。

+0

詳細情報(私がこのサイトで受け取った可能性のある最も詳細で徹底的な説明)がありがとうございました。私はあなたがこれでやっているところを理解し始めています(私はまだ比較的新しいです)が、resultDictは 'guard let resultDict = result as? [String:[[String:AnyObject]]] else {return} '。私は各行に折り返し点を置き、一度その行に当たると、残りのコードは実行されません。あなたが構造体を見ることができるように、FBSDK要求の出力全体を使って質問を更新します。 – winston

+1

@jamesああ、 'results'辞書の値は定数型ではありません。 。基本的には2回キャストする必要があります。 'results'を '[String:AnyObject]'に渡し、 ''データ ''値を取得したら、 '' AnyObject'から '[[String:AnyObject]]'にキャストできます。 – Hamish

+0

あなたの更新された答えが働いた!助けてくれてありがとう。私は間違いなく何が起こっているのか理解するためにこれを読んでいく必要があります(私はキャスティングで少し失われることを認めます)。私はフラットマップについても知らなかった。非常に便利!あなたはブログ/ウェブサイトを持っていますか?私はあなたからスウィフトを学び続けるのが大好きです。再度、感謝します! – winston

関連する問題