Facebook SDK 3.5 に移行してみた
一通のメール
FaceSync という Facebook の友達の画像を自分の連絡先にセットするだけのシンプルなアプリを公開しているのですが、4月中に facebook からこんなメールが来ているのに、ずっと気づかずスルーしていました。だって、登録メールアドレスに来なくて facebook の web のサイドメニューの下の方にちょろっとだけ「1」とかバッジが付いていても気づかないっす。
なんぞこれ、と思って開いてみると…
Please upgrade to the Facebook SDK 3.2.1 for iOS
This app uses an outdated version of the Facebook SDK for iOS. Please download the latest version: iOS SDK 3.2.1.
…中略…
Facebook will also stop supporting v2.0 of the SDK in June 2013, so you are advised to upgrade to the new SDK as soon as possible.
あぶなー
facebook SDK ver 2.0 のサポートは 2013年6月で終了するのでできるだけ早く移行しなさいって書いてある。
さっそく始めてみたのはいいのですが、ドキュメントの通りやってもなんだか上手くいかなくて少し苦労しました。
facebook SDK 3.5 の使い方そのものは開発者用のドキュメントに書かれているので、ここでは「よく読めば書いてあるかもしれないけど、ないかもしれない」注意点をまとめました。
SDK 3.5 でちょっとハマった点
基本的にはどれもちゃんとドキュメント読めば書いてあることのようですが、ななめ読みしたりググった情報が間違えていて逆に混乱したり。
Facebook App ID
以前は API を呼び出すときにソースコード内に Facebook App ID を記述していました。新しい SDK では plist ファイルの中に 「FacebookAppID」という key に 文字列として記述する方法に変更になりました。
FBSession
SDK 3.x では FBSession クラスを使うことでログインやセッション管理が楽になりました。FBSession クラスのセッションを有効にする方法はドキュメントを見たりサンプルを見るといくつかあるようなのですが、僕の FaceSync アプリのように単に自分や友だちの情報を取りたいだけ(後述の FQL でクエリをかけるだけ)なら、下記の方法が一番簡単そうです。
1 2 3 4 5 6 |
FBSession *session = [[FBSession alloc] init]; [FBSession setActiveSession:session]; [FBSession.activeSession openWithCompletionHandler:^(FBSession *session, FBSessionState status, NSError *error) { // ログイン後の処理 }]; |
2行目の setActiveSession を忘れていて openWithCompletionHandler でエラーになって若干ハマりました。
closeAndClearTokenInformation
ログアウトするときに closeAndClearTokenInformation を呼ぶのですが、これ、ハマりました。このメソッドを呼ぶとなぜか openWithCompletionHandler のハンドラーが直接呼ばれます。上のセッション作成のサンプルコードの5行目にいきなり飛びます。この openWithCompletionHandler の completion handler は実は close 時にも使われる open/close 用の完了ハンドラなのかもしれません。
なので、上記のセッション作成サンプルの opneWithCompletionHandler 以下を少し変更します。
1 2 3 4 5 |
[FBSession.activeSession openWithCompletionHandler:^(FBSession *session, FBSessionState status, NSError *error) { if (FBSession.activeSession.state == FBSessionStateOpen ) { // ログイン完了処理 } }]; |
違いは、open 時も close 時も同じハンドラが呼び出されるため、どっちで呼び出されたのかを調べるための条件式を追加した部分です。セッションのステートが open ならログイン完了処理を行い、そうじゃなければ特に何もしないようにしました。
locale を設定して日本語で結果を取得する
日本人の facebook ではローマ字表記の名前と漢字表記の名前の2種類が登録されている場合が多いかと思います。これは、日本に限らずロシア語やアラビア語など英語のアルファベットだけでは表記できない国すべてに当てはまります。
FaceSync では FQL(Facebook Query Language) を使用してクエリを投げてフレンド情報を取得しています。このとき、単に FQL を投げただけではローマ字表記の名前が返ってきてしまいます。以前の SDK 2.0 までは FQL とは別の API を利用すると日本語表記が取得できたのですが、今回の SDK 3.x からは使えなくなってしまったようです。
FQL を使ってフレンド名を日本語で取得するには次のように “locale” パラメータを設定して FQL を投げます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
NSString *strParam = [[NSString alloc] initWithFormat:@"SELECT uid, name, birthday_date, pic_square, pic_big FROM user WHERE uid IN (SELECT uid2 FROM friend WHERE uid1 = me())"]; // ロケールに "ja_JP" を設定 NSMutableDictionary *params = [NSDictionary dictionaryWithObjectsAndKeys:strParam, @"q", "ja_JP", @"locale",nil]; // FQL を投げる [FBRequestConnection startWithGraphPath:@"/fql" parameters:params HTTPMethod:@"GET" completionHandler:^( FBRequestConnection *connection, id result, NSError *error) { if (error) { NSLog(@"Error: %@", [error localizedDescription]); } else { NSLog(@"Result: %@", result); // "data" セクションに全フレンド情報が入っている NSDictionary *arrFriends = [result objectForKey:@"data"]; } }]; [strParam release]; |
上記の3行目で、”locale” に “ja_JP” を設定しています。この設定がない場合には、デフォルトのローマ字表記の名前が返ってきます。また、名前に限らずすべての内容が日本語表記になります。
ロケールの動的設定
上のロケール設定が “ja_JP” で固定であればよいのですが、FaceSync は世界中の言語に対応していますので、ユーザのロケールを調べて動的に設定しなくてはなりません。新しい SDK では startForMrWithCompletionHandler を使うと簡単に自分のプロフィールを取得できるのですが、ロケール情報を取得することはできないようです。
結局 FaceSync では FQL を使って自分のロケール情報を取得してからフレンド情報を取得する FQL に反映させることにしました。FQL を使用して自分のロケール情報を取得するには次のようにします。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
NSString *strParam = [[NSString alloc] initWithFormat:@"SELECT uid, locale, name, pic FROM user WHERE uid=me()" ]; NSMutableDictionary *params = [NSMutableDictionary dictionaryWithObjectsAndKeys:strParam, @"q", nil]; [FBRequestConnection startWithGraphPath:@"/fql" parameters:params HTTPMethod:@"GET" completionHandler:^(FBRequestConnection *connection, id result, NSError *error) { if (error) { NSLog(@"Error: %@", [error localizedDescription]); return; } else { // ロケール情報の取得 m_locale = [NSMutableString stringWithString:[me objectForKey:@"locale"]]; } }]; [strParam release]; |
1行目で FQL 文の中に “locale” 文字列をいれているのがミソです。これでレスポンスに locale 文字列が返されます。
こんな感じで、FaceSync の facebook SDK 3.5 対応をしました。これでしばらくそのまま使えればよいのですが。しょっちゅう新しい SDK に対応するのは大変です。
参考になりました。ありがとうございます。ちなみにこのアプリはダウンロードできませんと表示されますが、現在公開していないのでしょうか。
inu さん
はい、このアプリを公開していた頃は iOS 5.x でした。その後、6, 7, 8 と進むにつれて対応しなくてはならないことが増えたため、手が回らずにやむなく非公開とさせていただきました。
すいません、、、