※筆者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の送り方
- SLRequestの requestForServiceType を叩く.
- SLRequestの setAccount を使ってACAccountのインスタンスをアサイン
- 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 を修正
@interface SCSimpleSLRequestDemo : NSObject
- (void)fetchTimelineForUser:(NSString *)username;
@end
AppDelegate.m で fetchTimelineForUser をたたく
- (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で隠しましたが)コンソールにタイムラインのデータが無事読み込まれました
動かない場合はシミュレータ側にアカウントを紐付けているかもう一度確認してみてください.