質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Facebook Graph API

Facebook Graph APIとは Facebookのグラフデータベース用のAPIであり、対応言語はPHP、Perl、ActionScript、JavaScriptなどがあります。

Swift

Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

Q&A

解決済

1回答

2504閲覧

facebook Graph APIで、友達リストの取得

kazy1981

総合スコア44

Facebook Graph API

Facebook Graph APIとは Facebookのグラフデータベース用のAPIであり、対応言語はPHP、Perl、ActionScript、JavaScriptなどがあります。

Swift

Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

0グッド

0クリップ

投稿2016/12/29 16:25

編集2017/01/02 14:26

お世話になります。

こちらのページを参考にswiftでgraph APIを使用して自分のtaggable_friendsを取り出しています。

以下のコードで、問題なく、デバッグエリアに、自分の友達の名前がprint()関数により出せました。

class FriendsListViewController: UIViewController,{ var friendsData:[[String:Any]] = [] //facebookの友達リストの辞書を要素とする配列 (中略) func getFBfriends(){ FBSDKGraphRequest(graphPath: "me/taggable_friends", parameters: ["fields": "id, name, gender, age_range, locale, timezone, updated_time, first_name, last_name, picture.type(large), email"]).start(completionHandler: { (connection, result, error) -> Void in if (error == nil){ let dict:NSDictionary! dict = result as! [String : Any] as NSDictionary! self.friendsData = dict.object(forKey: "data") as! [[String:Any]] var mycount = 0 for friend in self.friendsData{ mycount += 1 print(String(mycount) + " :" + (friend["name"] as! String)) } }else{ print (error!) } }) } }

ところが、どうも不思議なことに、viewcontrollerのメンバ変数として定義したself.friendsDataをViewDidLoadで呼び出そうとしたら、空でした。当然、このgetFBfriends()よりも後で、呼び出しています。以下の状態です。

override func viewDidLoad() { super.viewDidLoad() self.getFBfriends() for friend in self.friendsData{ //ここはfriendsDataが空のため、呼び出されない } }

かなり邪推なのですが、FBSDKGraphRequestの呼び出しの中で行えることには制限があるような気がしているのですが、そうなのでしょうか?つまり、FBSDKGraphRequestの内部で行ったことはその外部には持ち出せない、など。。。

ひょっとするとswiftのとてつもなく基本的なところを見落としている気もしますが、graph APIの制限のような気もしており、自分で解決することが困難となり、質問させていただいた次第です。検索のキーワードだけでも結構ですので何かヒントをいただけますと幸いです。

facebook APIは、cocoa podで以下のとおりインストールし、当該viewcontrollerのswiftファイルで、import FBSDKCoreKit, import FBSDKLoginKitをしております。

pod 'FBSDKCoreKit' pod 'FBSDKShareKit' pod 'FBSDKLoginKit'

swift3, xcode 8.2.1です。

宜しくお願いいたします。

1月2日追記

Kentarou様のコメントで確実に前進しましたが(おそらくエスケープや”同期”などの仕組みが分かっておらず、以前完全にゴールできておりません・・)

以下の助言に基づき、以下のコードにいたしました。

var friendsString:[String] = [] override func viewDidLoad() { super.viewDidLoad() self.getFBfriends{ var mycount = 0 for friend in self.friendsData{ mycount += 1 print(String(mycount) + " in VDL :" + (friend["name"] as! String)) self.friendsString.append(friend["name"] as! String) self.friendsString.append("てすと") } } // self.setupFriends() print("ともだちすとりんぐ = \(friendsString)") } // getFBfriendsメソッド(Kentarou様のご提示のものそのままです) func getFBfriends(resultBlock: @escaping () -> Void) { FBSDKGraphRequest(graphPath: "me/taggable_friends", parameters: ["fields": "id, name, gender, age_range, locale, timezone, updated_time, first_name, last_name, picture.type(large), email"]).start(completionHandler: { (connection, result, error) -> Void in if (error == nil){ let dict:NSDictionary! dict = result as! [String : Any] as NSDictionary! self.friendsData = dict.object(forKey: "data") as! [[String:Any]] var mycount = 0 for friend in self.friendsData { mycount += 1 print(String(mycount) + " :" + (friend["name"] as! String)) } resultBlock() }else{ print (error!) resultBlock() } }) }

結果、非常に不思議ですが、print分ではin VDL部分は表示されるものの、friendsStringは空でした。for friend in self.friendsDataループ内でブレークポイントを設定してデバッグすると確かにfriendsStringに友達の名前が入っているのですが、ループを出た時にリセットされる(?)ようです。

おそらくクリティカルに何らかの理解が欠落しているのだと思いますが、恐縮ながらあと一歩ご助言いただければと存じます。

宜しくお願いいたします。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

func getFBfriends()メソッドの中で友達を取得する通信が行われていると思うので、通信が戻る前にviewDidLoad()を抜けてしまっているのでしょうね。

非同期の通信の場合はいつレスポンスが戻ってくるのかわからないので、その後にやりたいことがある場合処理を戻してあげる必要があります。

以下の様にすることで通信後にメソッドの後ろにあるブロック部分が呼ばれます。

swift

1 2// 呼び出し方 3self.getFBfriends { 4 5 // getFBfriendsの処理が終わった時にこのブロックの中が呼ばれる 6 for friend in self.friendsData{ 7 8 } 9} 10 11 12 13// getFBfriendsメソッド 14func getFBfriends(resultBlock: @escaping () -> Void) { 15 16 FBSDKGraphRequest(graphPath: "me/taggable_friends", parameters: ["fields": "id, name, gender, age_range, locale, timezone, updated_time, first_name, last_name, picture.type(large), email"]).start(completionHandler: { (connection, result, error) -> Void in 17 if (error == nil){ 18 let dict:NSDictionary! 19 dict = result as! [String : Any] as NSDictionary! 20 21 self.friendsData = dict.object(forKey: "data") as! [[String:Any]] 22 23 var mycount = 0 24 for friend in self.friendsData { 25 mycount += 1 26 print(String(mycount) + " :" + (friend["name"] as! String)) 27 } 28 29 resultBlock() 30 }else{ 31 32 print (error!) 33 resultBlock() 34 } 35 }) 36}

投稿2016/12/29 23:16

_Kentarou

総合スコア8490

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

kazy1981

2017/01/01 23:38

Kentarou様、早速のご回答ありがとうございます(すいません、なぜかメール通知が切れており返信遅くなりました。) 正直申し上げて、エスケープや、”同期”の部分の意味がいまいちわかっておりませんが、まずはいただいたコードで実行しました。ところが、残念ながら依然として友達リストが取れませんでした。質問を編集してトライしたコードをつけました。もし可能でしたら再度コメントいただければ大変嬉しく思います。宜しくお願いいたします。
kazy1981

2017/01/01 23:49

すいません、もう少しちゃんと自分で見てみてからご返信すべきでした。再度検証しております。
kazy1981

2017/01/02 08:50

参考ページ拝見しました。おそらくかなり似たことですね。勉強いたします。一方、もし上記再質問にもコメントいただけますと幸いです。。
kazy1981

2017/01/02 23:59

非同期処理についてよくわかりました。 結局やりたいことは、取得した友達リストをtableviewに表示したかったのですが、.reloadDB()をresultBlock()の中にわたしてやることで解決しました! どうもありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問