ソーシャル/クラウドサービスSDK、よもやま話
いろんなサービスのiOS用SDKを触った感想なぞ。
tottepostでは、Facebook/Twitter/Flickr/Dropbox/Picasa/Evernote/Minus/Mixi/Fotolifeの9つが使えます。
SDKのオレオレランキングを発表するとですね、
Dropbox > Facebook, Twitter > Flickr > Picasa > Evernote >>>>> Mixi
って感じ。
Minusは自分で作ったので対象外で、FotolifeはSDK提供してないので選外。
まぁ、MixiSDKの愚痴を言うためのエントリだと思ってくださいw
苦労話
色々なサービスのSDKを使ってみましたが、SDKのコードを修正する事なしに使えたのはFlickr、Dropbox、Picasaだけでした。
Dropboxサイコー!
Facebookは、NSURLDatadelegateのない時代のコードなので、プログレスが取得できず、カテゴリを使って拡張しました。過去の記事に詳細があります。
Twitterも、そのまま使うとプログレスが取得できないので、signedURLRequestを使う必要がありました。その辺りは、この記事に書きました。
Flickrは、objectiveFlickrをつかってます。まぁ可もなく不可もなく。
Evernoteに関しては、公開されているEDAMというAPIのSDKが同期的な通信しかサポートしていないので、新しくEVNConnectというライブラリを作りました。興味のある方は、EVNConnectの記事をどうぞ。
Minusは元々、iOS用のSDKがない…のでMinusConnectというライブラリを作った。MinusConnectの記事をご覧くださいませ。
Fotolifeは、AtomPubという旧時代のAPIで認証がWSSEでした。objc-atompubというライブラリを見つけたのですが、iOS向けではないので、forkしてiOS5対応にしました。コードは、kent013/objc-atompub · GitHubに置いてあります。
Picasaに関しては、GData Objective-C Client Setup in XCode 4 « Kelvin's BlogあたりにXCode4で使うための設定が書いてあります。たしかにそのまま使えたんだけども…GData APIはGoogleすべてのサービスをカバーしているだけあって、ドキュメントが膨大。写真アップロードしたいだけなのに、どうやったら良いのかが分からず迷子になって時間がかかりました...Google先生もちゃんと答えてくれないしさ。
Mixiは...SDKあるんだけど、バグがあるしドキュメント日本語しかないし、Mixiアプリの説明とMixiGraphAPIの説明がごっちゃになってるし、SDKオープンソースじゃねぇし、やるきあんのかxx野郎って思いました。
最初、OAuthなのにMixiアプリ経由でしか認証できなかったので、思わず、は?って言ったのを覚えています。
たしか、先月中旬くらいのアップデートでWebViewを使った認証がサポートされましたが、バグがあったのとdelegateでリクエスト本体を渡してくれない仕様だったので直して使ってます。最新版では直ってるかもしれませんが。
まぁ、一番アレなのは、SDKに対して文句を言う場所がないことなんですがね。
ログイン周り
- クライアントが認証に必要なUIを用意しなくて良い
- クライアントがユーザー名やパスワードを保存しなくて良い
- クライアントが認証方法を意識しなくていい
あたりが重要な要素かな。例えば、Dropboxだと
[[DBSessionsharedSession] link];
Facebookだと
NSArray *permissions = [NSArrayarrayWithObjects:@"publish_stream", @"user_location", @"user_photos", @"offline_access", nil]; [facebook authorize:permissions];
だけです。PicasaやMixiは、ログイン用のUIが特別に用意されているのでそれを表示する実装をしなければならないです。
そのかわり、FacebookやDropboxの場合はアプリの切り替えが発生するのでその処理を書かなければならないですが。
それから、クライアント側でユーザ名とパスワードを保存しなきゃならない実装は微妙だなーって思います。認証の問題なんだけど、FotolifeはWSSEだから保存しなきゃ行けないし、MinusはOAuth2なのにPassword認証しかサポートしてないという...
あと、認証画面ね。アプリが認証画面をだす実装は、アプリの実装に影響を与える(UINavigationControllerにpushするか、presentModalViewしたいのかとか)からあんまり好きじゃないなぁ。アプリが入ってないと認証できない仕様は論外としてだね。やっぱりアプリが入っていればアプリで、入ってなければSafariで認証してくれるほうが楽。
リクエスト周り
特にDelegateが問題になるかなと思います。
- 非同期通信
- クライアントからリクエスト本体を知る事ができる
- Delegateメソッドがリクエストの種類ごとに分かれている
が重要ですね。非同期通信なのはマストだと思います。Evernoteが同期通信を採用していましたが、それはEvernoteだとあまり非同期に通信する事がないからなのでしょうか。
で、Mixiがそうでしたが、クライアント側からリクエスト本体を知る事ができないと、delegateが提供されていても「通信が終わった」ことしか分からないです。
- (void)mixi:(Mixi*)mixi didSuccessWithJson:(id)data;
とか微妙すぎます。せっかくMixiオブジェクトもらえるのに、その通信がなんなのかが分からないってのはどういう実装なのか。
- (void)mixi:(Mixi*)mixi andConnection:(NSURLConnection *)connection didFinishLoading:(NSString*)data;
こうなっていれば、
NSString *url = [connection.currentRequest.URL absoluteString]; NSString *method = connection.currentRequest.HTTPMethod; if([url isMatchedByRegex:@"token"]){ }elseif([url isMatchedByRegex:@"albums/@me/@self"] && [method isEqualToString:@"POST"]){ }
のように処理分けする事ができます。で、まぁ最低限、connectionとかそれをラップしたクラスがdelegateメソッドに渡されていれば処理分けできるので良いのですが、Dropboxは、
[restClient uploadFile:filename toPath:toPath withParentRev:nilfromPath:path];
に対応するdelegateとして
- (void)restClient:(DBRestClient*)client uploadedFile:(NSString*)destPath from:(NSString*)srcPath metadata:(DBMetadata*)metadata; - (void)restClient:(DBRestClient*)client uploadFileFailedWithError:(NSError *)error; - (void)restClient:(DBRestClient*)client uploadProgress:(CGFloat)progress forFile:(NSString*)destPath from:(NSString*)srcPath;
が用意されており、createFoloderなら、それ専用のdelegateが用意されています。
これだと確かにコードは長くなりますが、見通しはよくなりますよね。
どこに何を書けば良いのかが分かりやすいし、何より、なにを使えば処理分けできるのかを調べなくていいので楽です。
あとは、atompubなFlickrのAPIはAPIの実装が微妙で、postURIがアルバムのIDを知っているだけじゃ構成できなくて、postする前に問い合わせなきゃいけなくて。あと、空のアルバムを作れないってのが一番辛かった...