Social.framework & Account.framework

社内のスマホエンジニア勉強会で発表したのでブログにしときます。

サンプルアプリはGitHubに公開しているのでどうぞ。
https://github.com/i2key/SocialframeworkExample

最初のほうは当たり前なツイートシートとかの内容なので、試してて引っかかったところのみ掲載します。
Facebookに対してAPIコールを行う(SLRequestを使う)場合、パーミッションFacebookの指定する順序で取得しないといけません。

基本的には以下の順にパーミッションをとる必要があります。
Step 1: Request basic profile information
 ex) email, user_birthday , user_location
Step 2: Request read permissions
 ex) user_about_me, read_stream
Step 3: Request publish permissions
 ex) publish_actions, publish_stream
参考:https://developers.facebook.com/docs/howtos/ios-6/

そのため、最初からemail,publish_action のような組み合わせではパーミッション取得時に以下のようなエラーがでます。

The Facebook server could not fulfill this access request: The app must ask for a basic read permission at install time.

例えば、FacebookAPIをSLRequestで叩いてウォールポストを行いたい場合。
準備として・・・
FacebookのAPP登録画面(https://developers.facebook.com/apps)にてAppIDを発行します。
・「アプリをFacebookに統合する方法を選択」にて「ネイティブiOSアプリ」のバンドルIDを入力します。
・「詳細設定」の「認証」でAppTypeを「Native/Desktop」。AppSecretinClientを「いいえ」

初めにemailのパーミッションを取得します。(上記step1)

ACAccountType *facebookType
 = [self.accountStore accountTypeWithAccountTypeIdentifier:ACAccountTypeIdentifierFacebook];
NSDictionary *options = @{
                        ACFacebookAppIdKey : @"AppID",
                        ACFacebookPermissionsKey : @[@"email"],
                        ACFacebookAudienceKey : ACFacebookAudienceOnlyMe};

[self.accountStore requestAccessToAccountsWithType:facebookType 
                                               options:options
                                            completion:^(BOOL granted, NSError *error) {
        if(granted){
            //ActionSheet表示する処理
        }
}]

次にpublish_actionsのパーミッションを取得して(上記step3)、ポストします。

ACAccountStore *accountStore = [[ACAccountStore alloc] init];
ACAccountType *facebookType = [accountStore accountTypeWithAccountTypeIdentifier:ACAccountTypeIdentifierFacebook];
    
NSDictionary *options = @{ACFacebookAppIdKey : @"AppID",
                        ACFacebookPermissionsKey : @[@"publish_actions"],
                            ACFacebookAudienceKey : ACFacebookAudienceOnlyMe};
    
[accountStore requestAccessToAccountsWithType:facebookType options:options completion:^(BOOL granted, NSError *error) {
    if(granted){
        NSString *urlStr = [NSString stringWithFormat:@"https://graph.facebook.com/me/feed"];
        NSURL *url = [NSURL URLWithString:urlStr];
        NSDictionary *params = @{@"message" : @"hogehoge"};
           
        SLRequest *request = [SLRequest requestForServiceType:SLServiceTypeFacebook
                                                    requestMethod:SLRequestMethodPOST
                                                              URL:url parameters:params];
            
        [request setAccount:self.selectedAccount];
        [request performRequestWithHandler:^(NSData *response, NSHTTPURLResponse *urlResponse, NSError *error){
            NSLog(@"response:%@",[[NSString alloc]initWithData:response encoding:NSUTF8StringEncoding]);
        }];
    }
}];

これでエラーが出ずにFacebookAPIを利用したポストが出来ます。

また、上記のようにやってもどうしてもエラーが出る場合は、iPhone側の設定にて、アプリとFacebookの連携の許可を一旦解除して、再度アプリからaccountStoreにアクセスすると直る場合があります。