THTTPClientに手を加えてiOSからEvernoteへ非同期でアクセスする


Evernote SDKに入ってるiOS向けサンプル1はあっさりEvernoteにアクセス出来て非常に楽ちんなんですが、ひとつ大きな問題があります。

Evernoteアクセスの部分が同期処理なので、httpリクエスト処理中の進捗が取れません。
文字情報だけならあまり問題ないと思いますが、pdfや画像データなど大きめのデータを3G回線で扱ったりすると数十秒だんまり状態になり、ユーザーに優しくありません。

というわけで、改造しましょう。

サンプル内のEvernote.mを見ると、Evernoteとのやりとりに使うオブジェクトはこんな感じで生成されています。

NSURL * NSURLuserStoreUri = [[[NSURL alloc] initWithString: userStoreUri] autorelease];

THTTPClient *userStoreHttpClient = [[[THTTPClient alloc] initWithURL:  NSURLuserStoreUri] autorelease];
TBinaryProtocol *userStoreProtocol = [[[TBinaryProtocol alloc] initWithTransport:userStoreHttpClient] autorelease];
EDAMUserStoreClient *userStore = [[[EDAMUserStoreClient alloc] initWithProtocol:userStoreProtocol] autorelease];

ここで生成されているTHTTPClientが持つflushというメソッドがNSURLConnectionを使って通信を行います。

その部分が

[NSURLConnection sendSynchronousRequest: mRequest returningResponse: &response error: &error];

こんな感じで完全に同期処理になってしまっているので、通信が終わるまで処理の進捗が分かりません。

ここを、こんな感じに変更します。

NSURLConnection *urlConnection_;
urlConnection_ = [[NSURLConnection alloc] initWithRequest:mRequest delegate:self startImmediately:YES];
while (!completed_) {
    [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
}

非同期リクエストの後whileループを回しているのは、通信が終わるのを待つためです。
flushというメソッド自体はthrift側から同期的に通信処理を行うことを期待されているので、そこは変えられないためです。
もしそこまで変えようとするとthrift側のコードを全部取っ替えなければいけなくて死にます。

なので、Evernoteアクセス自体はNSOperationを使うなり、performSelectorInBackground:withObject:を使うなり、メインスレッドとは別に実行しましょう。

NSRunLoopを呼び出しているのは無限ループを使う場合のお約束ですね。
きちんと呼んでおかないとNSURLConnectionのdelegateが呼ばれなかったりすると思います。

これらの変更はTHTTPClientを改造するのではなく、THTTPClient<NSURLConnectionDelegate>を派生して新たに作る方がいいでしょう。

あとは、delegateに指定したクラスに対してNSURLConnectionのプロトコルが呼ばれるようになります。

そんな感じで実装したのが以下のソースです。

https://raw.github.com/fifnel/RollToEver/master/RollToEver/Classes/THTTPAsyncClient.h
https://raw.github.com/fifnel/RollToEver/master/RollToEver/Classes/THTTPAsyncClient.m

fifnel/RollToEver · GitHub
https://github.com/fifnel/RollToEver


  1. Cloud API | Evernote Corporation
    http://dev.evernote.com/documentation/cloud/
    evernote-api-1.20.zip 内の /cocoa/sample にサンプルがあります。 

Leave a Comment

Trackbacks and Pingbacks: