ObjectiveFlickrをiPhoneで使う OAuthログイン & API実行編

ログインの基本的な流れとしては
1.[OFFlickrAPIContext loginURLFromFrobDictionary:requestedPermission:]で生成されたURLを[UIApplication openURL:]で開き、
2.その中でユーザーが認証され、
3.コールバックのURLSchemeでアプリが開かれ、[UIApplicationDelegate application:handleOpenURL:]が呼ばれるのでそこでfrobを得て、
4.それを用いて"flickr.auth.getToken"APIを呼びだし、アクセストークンを取得する
という風になると思います。


こうする事で2.ではSafariが開かれているのでURLを見てパスワードを入力していいサイトかどうかユーザーが判断できますし、OAuthの認証とアプリ起動をスムーズにできます。URLSchemeを使わず、UIWebViewを用いるやり方だとユーザーがアプリ自体にパスワードを晒した事になったり、正しいサイトにパスワードを入力しているのかどうか判断が付かなくなったりするのでよくないです。


サンプルコードはobjectiveflickr同梱ExampleのSnapAndRunが詳しいのでそちらを参照。
上の流れは丁度、
1.[SnapAndRunViewController authorizeAction]
3.4.[SnapAndRunAppDelegate application: handleOpenURL:]
4.[SnapAndRunAppDelegate flickrAPIRequest: didCompleteWithResponse:]
にあたります。

ObjectiveFlickrをiPhoneで使う 準備編

2.0でiPhoneにも対応したObjectiveFlickr2.0を試してみたのでメモを。

I.flickrAPIキーを取得する

http://www.flickr.com/services/apps/create/
商用非商用で少し手続きの煩雑さが変わるみたいですが、どんなプラットフォームの何をするアプリなのかを詳細に説明する事が必要です。

trust us when we say you can't be detailed enough

との事なので初めからきっちりと説明した方が早く申請が通るようです。(非商用だとすぐAPI Keyがもらえます。)

II.flickr側の設定を整える

APIキー表示画面から、 Edit auth flow for this app を選択し、次の二つを設定。

  • App Type
    • Web Applicationを選択
  • Callback URL
    • YourAppURLSchemeName://auth? にする

YourAppURLSchemeNameは自分のアプリのURLスキーム名にする。*1

III.アプリ側の設定を整える

Info.plistにURL typesやURL Schemesを追加する。
URL Schemesに不慣れだったので、特にURL schemeを使ってアプリを起動する - 強火で進めを参考にさせていただきました。画像を用いて解説されていてわかりやすいのでそちらを参照。
上のサイトでは${PRODUCT_NAME}をスキーム名に指定していますが、こちらではflickrでCallback URLに設定した値に合わせます。

IV.objectiveflickrをプロジェクトに追加する

iPhoneだとMac用アプリのようにビルドしたフレームワークをコピーさせるだけでは使えないです。READMEにあるよう追加して、静的にリンクさせます。
1.自分のiPhoneアプリのプロジェクトを開き、Project -> Add to Project...でObjectiveFlickr.xcodeprojを追加。
2.Target Info の Generalタブにて次のように追加

  • Direct Dependencies
    • ObjectiveFlickr (library)を追加
  • Linked Libraries
    • CFNetwork.framework を追加

3.Target Info の BuildタブでAll Configurationsの"Header Search Paths"にObjectiveFlickrのSourceディレクトリとLFWebAPIKitディレクトリのパスを追加。
4.Targetsツリーの中にある、Link Binary With LibrariesにlibObjectiveFlickr.aをドラッグアンドドロップ


以上で準備は完了です。

*1:objectiveflickrのサンプルプログラムを動かす時は"snapnrun://auth?"にする

UIViewのアニメーションを滑らかに動かす

UIViewのsetAnimationCurve:(UIViewAnimationCurve)で指定できるイージングはたったの四種類で表現力に乏しい。そこでもっと自由にUIViewを動かしたい場合、CAMediaTimingFunctionを指定してLayerを動かすとうまくいく。

UIView *moveView;
CALayer *moveLayer;
CABasicAnimation *moveAnim;
CAMediaTimingFunction *timingFunc;


timing = [CAMediaTimingFunction functionWithControlPoints:0.3f :0.8f :0.8f :1.0f];//(0,0),(0.3,0.8),(0.8,1.0),(1,1)の四点で描かれるベジエ曲線様のイージング


moveLayer = moveView.layer;
moveAnim = [CABasicAnimation animationWithKeyPath:@"position"];//Animatableなプロパティならposition以外でも可能
moveAnim.timingFunction = timing;
//moveAnim.* = * //いろいろ省略
[moveLayer addAnimation:moveAnim forKey:kCATransition];

これで指定できるイージングは四点で指定されるベジエ曲線状のものだけなので、もっと細かく決めたい場合、アニメーションを分割するかCAKeyframeAnimationを使うかする必要があるようだ。

TextFieldがキーボードに隠されないようにする

TextFieldを全画面のUIScrollViewのscroll上に配置しておく。TextFieldDelegateに次のように書くとテキストフィールドが隠れない。

- (void)textFieldDidBeginEditing:(UITextField *)tf {
	NSInteger marginFromKeyboard = 10,keyboardHeight = 165;//interfaceOrientationによる

	CGRect tmpRect = tf.frame;
	if((tmpRect.origin.y + tmpRect.size.height + marginFromKeyboard + keyboardHeight) > scroll.frame.size.height){
		NSInteger yOffset;
		yOffset = keyboardHeight + marginFromKeyboard + tmpRect.origin.y + tmpRect.size.height - scroll.frame.size.height;
		[scroll setContentOffset:CGPointMake(0,yOffset) animated:YES];
	}
}

- (void)textFieldDidEndEditing:(UITextField *)tf {
	[scroll setContentOffset:CGPointMake(0,0) animated:YES];
}

UIによってはx方向のOffsetも変更したり、元のscrollViewのオフセットを記憶しておいてその値に戻す方がいいかもしれない。

iPhoneアプリ内からアプリを終了させる

非公開メソッドだが、exit()を使うより終了時の様々な事をやってくれる。applicationWillTerminateに設定類を保存する処理を書いていて、アプリ内からアプリを終了させたい時とかには使えそう。

[[UIApplication sharedApplication] terminateWithSuccess];

IBを使わずにリターンキー押下時にキーボードを隠す

簡易的にIBを使わずにリターンキー押下時にキーボードを隠すには、対象のUITextFieldにdelegateを設定してやり、UITextFieldDelegateのtextFieldShouldReturn:をこんな風に実装してやるといい。

- (void)textFieldShouldReturn:(UITextField *)tf {
	if( [tf canResignFirstResponder] ) [tf resignFirstResponder];
}

本来Returnキーの動作がデフォルト動作か否かを聞くメソッドだけれど、丁度いい時に呼ばれるメソッドなので。

iPhoneでflickrAPIを扱う方法

1.CのAPIライブラリを使う
Objcetive-CはC言語を内包しているのでflickrcurlライブラリ(http://librdf.org/flickcurl/ )で間に合うかもしれない。
利点

  1. おそらく楽
    • flickcurlオブジェクトを作ってflickrcurl_set_api_keyしてほげほげするだけでいいみたい。実際にiPhone上で試してはいないが。

欠点

  1. 基本的に同期的にしか動かない
    • 特に写真という比較的大きなデータを使うので何の工夫も無く使うと大変


2.Objective-CAPIライブラリを使う
Objective-CならObjective-Cのライブラリを使いたい。ObjectiveFlickr(http://lukhnos.org/objectiveflickr/ )を使えるかもしれない。
利点

  1. Ruby対応らしい
  2. Cocoaっぽく慣れ親しんだdelegateとかの方法で非同期的に書ける。


欠点

  1. iPhone未対応

Support for the-device-and-the-OS-that-shalt-not-be-named-until-July-11th

    • と目標にしているけれどまだの様子。
      Googleグループで議論されていたけれどどうも上手くいかず。
  1. ドキュメントにtypoが多い
    • 細かい事だけどやっぱりドキュメント読んでて疲れる。

Objective-Cをうまい事ハックしててOFFlickrInvocationというオブジェクトに直接flickrAPIをメソッドとして投げるような事ができるらしい。利点とも欠点とも。


3.地道にNSURL*とNSXML*を使う
利点

  1. 確実に動く

欠点

  1. NSXML*があまり高機能ではない