Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
Help us understand the problem. What is going on with this article?

iOS 7でTwitterのTLを取得するまでのまとめ(2013-10-08版)

More than 5 years have passed since last update.

※筆者Objective-C歴1ヶ月の初心者ですが勉強の為書かせて頂きます お見苦しい箇所等御座いますがご容赦ください.(何かありましたらコメント是非お願い致します)

↓このページを雑に翻訳させて頂きたいと思います↓

API requests with SLRequest
https://dev.twitter.com/docs/ios/making-api-requests-slrequest

概説

SocialクラスのSLRequestというのを使います REST API(ツイートの取得や投稿等Twitterとの情報をやりとりする仕組み)を叩いてくれます
Twitter API v1.1の全てのREST APIに対する request は認証(OAuth)が必要です.

ざっとrequestの送り方

  1. SLRequestの requestForServiceType を叩く.
  2. SLRequestの setAccount を使ってACAccountのインスタンスをアサイン
  3. SLRequestの performRequestWithHandler を叩く

例-ユーザのタイムライン取得

まずプロジェクトにSocial.frameworkとAccounts.frameworkを紐付けましょう

// SCSimpleSLRequestDemo.m
#import <Accounts/Accounts.h>
#import <Social/Social.h>
#import "SCSimpleSLRequestDemo.h"

アカウント情報を持つインスタンスをつくります
@interface@end の間に入力します

@property (nonatomic) ACAccountStore *accountStore;

initです
accountStoreを初期化します

- (id)init
{
  self = [super init];
  if (self) {
    _accountStore = [[ACAccountStore alloc] init];
  }
  return self;
}

次にiDeviceになにかTwitter アカウントが紐付いているか問い合わせる(BOOL)userHasAccessToTwitter です.(シミュレータだと必ず YES を返してくるらしい・・・)

- (BOOL)userHasAccessToTwitter
{
  return [SLComposeViewController
          isAvailableForServiceType:SLServiceTypeTwitter];
}

SLComposeViewControllerというのはiOSプリインのTwitter共有する画面のやつです.Safariでページを共有しようとすると出てくるアレ
これにiDeviceにアカウントがあるか問い合わせるメソッドがあるようです

最後にTimelineを取得する(void)fetchTimelineForUserです ゆっくり行きたいと思います.

iDeviceにTwitter アカウントがあるか確認する

さっき作ったuserHasAccessToTwitterをたたけば一発ですね.

- (void)fetchTimelineForUser:(NSString *)username
{
  //  Step 0: Check that the user has local Twitter accounts
  if ([self userHasAccessToTwitter]) {

紐付けられているアカウントが特にない場合このプログラムは終了します
else 節でNSLog吐かせても良いと思います

アカウントへのアクセス

//  Step 1:  Obtain access to the user's Twitter accounts
ACAccountType *twitterAccountType =
 [self.accountStore accountTypeWithAccountTypeIdentifier:
  ACAccountTypeIdentifierTwitter];

ACAccountType の accountTypeWithAccountTypeIdentifier メソッドでiDeviceに紐付いている指定したSNSのアカウントのひな形を持ってこれます(?).
今回は Twitter なので引数に ACAccountTypeIdentifierTwitter を指定していきましょう

[self.accountStore
     requestAccessToAccountsWithType:twitterAccountType
     options:NULL
     completion:^(BOOL granted, NSError *error) {

次です
ここに来て,最初に作っておいた accountStore インスタンスを使っていきます
たたくのは requestAccessToAccountsWithType メソッドです.これがユーザの保護された領域にアクセスする権限を取りに行ってくれます
typeは twitterAccountType optionsは特にないので NULL completionですがブロック変数を
書いていきます.※ブロック変数についてはこちらを参照してください

リクエストの生成

if (granted) {
         //  Step 2:  Create a request
         NSArray *twitterAccounts =
         [self.accountStore accountsWithAccountType:twitterAccountType];
         NSURL *url = [NSURL URLWithString:@"https://api.twitter.com"
                       @"/1.1/statuses/user_timeline.json"];
         NSDictionary *params = @{@"screen_name" : username,
                                  @"include_rts" : @"0",
                                  @"trim_user" : @"1",
                                  @"count" : @"1"};
         SLRequest *request =
         [SLRequest requestForServiceType:SLServiceTypeTwitter
                            requestMethod:SLRequestMethodGET
                                      URL:url
                               parameters:params];

         //  Attach an account to the request
         [request setAccount:[twitterAccounts lastObject]];

if(granted) ですがまずこのメソッドが通ったか通っていないかでフィルターをかけます(?).通らなければ後の else 節でNSLogを吐きます
通った場合, まずaccountStore の accountsWithAccountType メソッドをたたき,iDeviceに入っているTwitter アカウントたちを配列で取得します.
次にNSURLクラスでTLを取得するAPIのURLを持たせて
NSDictionaryクラスのparamsに今回拾いたい値を入れていきます

最後にSLRequestのオブジェクトを requestForServiceType メソッドで初期化しておきます
初期化できたら setAccount メソッドでtwitterAccounts配列にある最後のアカウントを指定しておきます.

リクエストの実行

//  Step 3:  Execute the request
         [request performRequestWithHandler:
          ^(NSData *responseData,
            NSHTTPURLResponse *urlResponse,
            NSError *error) {

           if (responseData) {
             if (urlResponse.statusCode >= 200 &&
                 urlResponse.statusCode < 300) {

               NSError *jsonError;
               NSDictionary *timelineData =
               [NSJSONSerialization
                JSONObjectWithData:responseData
                options:NSJSONReadingAllowFragments error:&jsonError];
                if (timelineData) {
                 NSLog(@"Timeline Response: %@\n", timelineData);
               }
               else {
                 // Our JSON deserialization went awry
                 NSLog(@"JSON Error: %@", [jsonError localizedDescription]);
               }
             }
             else {
               // The server did not respond ... were we rate-limited?
               NSLog(@"The response status code is %d",
                urlResponse.statusCode);
             }
           }
         }];
       }
       else {
         // Access was not granted, or an error occurred
         NSLog(@"%@", [error localizedDescription]);
       }
     }];
  }
}
@end

最後までいってしまいましたが,1行ずつ見ていきましょう
早速requestの performRequestWithHandler を使います
ここにもブロック構文が入ってます
宣言するのは返ってきたつぶやきのデータを格納する(?)NSData型のresponseData,NSHTTPURLResponse型のurlResponse,あとNSErrorのerrorとなります

responseDataが返ってきたらurlResponseのHTTPステータスコードを確認します HTTPステータスコードですが,

数字 意味
1xx 情報
2xx 成功
3xx リダイレクション
4xx クライアントエラー
5xx サーバエラー

です.これが200台でなければエラーなのでそれをチェックします.

これから responseData を解体していきます
まず json の解体に失敗した場合のために NSError 型のオブジェクトを持っておきます
次に NSDictionary の timelineData オブジェクトを NSJSONSerialization クラスの JSONObjectWithData メソッドで初期化していきます.引数に入れるのは responseData
options に NSJSONReadingAllowFragments , error は jsonError オブジェクトです.
NSJSONReadingAllowFragments ですが,「断片化を許容する」という感じの意味っぽいです.

timelineData が存在すればそれをコンソールに書き出していきます.そうでなければ JSON Error ということで localizedDescription メソッドでエラーメッセージを書きだしてもらいます.
次の else 節は urlResponse の statusCode が200台でなかった場合のものですがここではその statusCode を書き出してエラーメッセージということにしています.
最後の else 節は accountStore の requestAccessToAccountsWithType が失敗した時のものですね.

テストしてみた

Xcode で Empty Application → TwitterExample というプロジェクト名で開始
上記のように SCSimpleSLRequestDemo.m を作って(スーパクラスは適当に NSObject とかで?),適宜 SCSimpleSLRequestDemo.h を修正

SCSimpleSLRequestDemo.h
@interface SCSimpleSLRequestDemo : NSObject

- (void)fetchTimelineForUser:(NSString *)username;

@end

AppDelegate.m で fetchTimelineForUser をたたく

AppDelegate.m
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{

    SCSimpleSLRequestDemo *request = [[SCSimpleSLRequestDemo alloc] init];
    [request fetchTimelineForUser:@"(取得したい Twitter アカウントID)"];

    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
    // Override point for customization after application launch.
    self.window.backgroundColor = [UIColor whiteColor];
    [self.window makeKeyAndVisible];

    return YES;

}

iPhone シミュレータで事前に何か1つ以上Twitter アカウントを連携させておく.
これで Run を押せば

2014-09-06 13:36:34.542 TwitterExample[0000:0x00] Timeline Response: (
        {
        contributors = "<null>";
        coordinates = "<null>";
        "created_at" = "Sat Sep 06 00:00:00 +0000 2014";
        entities =         {
            hashtags =             (
            );
            symbols =             (
            );
            urls =             (
                                {
                    "display_url" = "xxxxxxxx";
                    "expanded_url" = "http://xxxxxxxx";
                    indices =                     (
                        00,
                        00
                    );
                    url = "http://t.co/xxxxxxxxx";
                }
            );
            "user_mentions" =             (
            );
        };
        "favorite_count" = 0;
        favorited = 0;
        geo = "<null>";
        id = 000000000000000000;
        "id_str" = 000000000000000000;
        "in_reply_to_screen_name" = "<null>";
        "in_reply_to_status_id" = "<null>";
        "in_reply_to_status_id_str" = "<null>";
        "in_reply_to_user_id" = "<null>";
        "in_reply_to_user_id_str" = "<null>";
        lang = ja;
        place = "<null>";
        "possibly_sensitive" = 0;
        "retweet_count" = 0;
        retweeted = 0;
        source = "<a href=\"https://hoge" rel=\"nofollow\">Twitter for Websites</a>";
        text = "JSONObjectWithData:options:error: XXXX - XXXX http://t.co/xxxxxxxxx";
        truncated = 0;
        user =         {
            id = 00000000;
            "id_str" = 00000000;
        };
    }
)

このように(プライバシーの為適宜0なりXで隠しましたが)コンソールにタイムラインのデータが無事読み込まれました
動かない場合はシミュレータ側にアカウントを紐付けているかもう一度確認してみてください.

keisei_1092
よろしくお願いします。
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away