2009年7月19日日曜日

YourTurn 1.1 サブミットしました

YourTurn 1.1をApp Storeにサブミットしました。現在レビュー待ちです。
http://wiki.github.com/akisute/YourTurn


■そもそもこのアプリ何?
学会タイマーアプリといえばわかりやすいと思います。要するに参加者ごとに時間を決めて割り振り、時間が来たらタイマー音がなる、それだけのアプリです。





2分程度のビデオデモを作ってみましたので、よろしければご覧ください(無音ですけど・・・)。


順調にレビューが進めば2週間後の8月上旬にはストアに並ぶと思います。無料、というかソースも全部公開してます。気が向いたらプレゼンしたりするときにでも使ってやってください。

iPhone OS 3.0のTableViewでscrollEnabledをNOにするとtableView:didSelectRowAtIndexPath:が機能しない

http://forums.macrumors.com/showthread.php?t=470266

OS2.2のころはscrollEnabledをNOにしても正常にdidSelectRowAtIndexPathが動いていたので、これは正直結構困ります。仕方がないのでscrollEnabledを使うのを回避して、スクロールするように戻しました。OS 3.1では直っているとよいのですが。

iPhone付属のPhotos(写真)アプリのような、回転可能な全画面表示ビューを作る方法



Photos(写真)アプリに使われている、全画面ビューを真似して作ってみました。具体的には以下のような仕様になります。
  • ステータスバーの後ろも含め、ビューの内容が全画面(320x480)で表示される
  • 画面をタップするとステータスバーとナビゲーションバーが消える
  • もう一度タップすると再度表示される
  • iPhoneを傾けると画面が回転する
参考にしたページは以下のとおり。
http://life.ponpoko.tv/?p=533

また、サンプルソースも公開してます。こちらのソースの、- (void)fullScreenMode:(BOOL)mode animated:(BOOL)animatedがフルスクリーン表示を実現しているメソッドになります。


■注意
iPhone OS 3.0以上専用です。2.2以下では別の方法を取る必要があります。


■まずはStatus BarとNavigation Barを消す
http://life.ponpoko.tv/?p=533 こちらのページに書いてある内容を100%そのままパク参考にさせていただければ何も問題ありません。iPhone OS 2.2までは記載されている通りのworkaroundが必要になりますが、3.0以降ではバグが修正されているため、単にStatus BarとNavigation Barを消せばOKです。

ただし一点、[self.navigationController setNavigationBarHidden:YES animated:YES];を使うと、ナビゲーションバーが上方向に対してぴょこんと引っ込むようなアニメーションになります。ステータスバーはその場でフェードアウトして消えるので、なんだか不自然な感じに見えます。Photos.app(写真アプリ)など、iPhone標準のアプリと同様にナビゲーションバーをフェードアウトさせて消したい場合には、UIViewのアニメーション機能とalpha値を利用して以下のようにします。
    if (animated)
{
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.3];
}
self.navigationController.navigationBar.alpha = mode ? 0 : 1;
if (animated)
{
[UIView commitAnimations];
}
Three20プロジェクトのソースから拝借してきました><


■Viewを全画面配置する(Status BarとNavigation Barのあった場所にも描画させたい)
さんざん悩んだあげく、実はUIViewControllerにそのためのプロパティがあったと知り、ものすごく簡単に解決しました。
- (void)viewWillAppear:(BOOL)animated
{
[UIApplication sharedApplication].statusBarStyle = UIStatusBarStyleBlackTranslucent;
self.navigationController.navigationBar.barStyle = UIBarStyleBlackTranslucent;
// このUIViewController.wantsFullScreenLayoutをYESにするとフルスクリーン表示になる
self.wantsFullScreenLayout = YES;
}
ついでにステータスバーとナビゲーションバーを透明にして裏が透過するようにしてみました。


■ビューの回転に対応したい
何も考えずにshouldAutorotateToInterfaceOrientationすればいいだろう常考
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return YES;
}
とおもったら思わぬ落とし穴が。確かに全画面表示にした状態でビューを回転させたり、逆にナビゲーションバーが出ている状態でビューを回転させたりする分にはこれだけで全く問題ないのですが、
  1. ナビゲーションバーを消す(全画面表示にする)
  2. iPhoneを傾けてビューを回転させる
  3. 再度ナビゲーションバーを表示する
という手順を踏むと、再度表示したときにナビゲーションバーが崩れる問題が発生。結局ナビゲーションバーを消したり再表示したりする際に、以下のようなworkaroundをするハメに。
    // Force set the frame of the navigation bar
CGRect frame = self.navigationController.navigationBar.frame;
frame.origin.y = 20.0;
self.navigationController.navigationBar.frame = frame;


■全画面表示をしている画面から前の画面に戻るとバグる問題
これで完成かと思えば、最後にもう一つ落とし穴が。
  1. iPhoneを横向きに傾けて、Landscape表示にする
  2. ナビゲーションバーを表示する
  3. そのまま横向きになっている状態で、ナビゲーションバーの戻るボタンを押して、前の画面に戻る
  4. 前の画面に戻る際に、wantsFullScreenLayoutをNOにして通常画面モードにし、ステータスバーとナビゲーションバーのスタイルもDefaultに戻す
という風な操作を行うと、なぜかナビゲーションバーのスタイルだけがDefaultに戻らず、表示も崩れるという問題が発生しました。たぶんOS 3.0のバグだと思います。
いろいろ試してみた結果、全画面表示をしている画面ではなく、前の画面のviewWillAppearのタイミングで以下のコードを呼びだせば問題が解決しました。
- (void)viewWillAppear:(BOOL)animated
{
[UIApplication sharedApplication].statusBarStyle = UIStatusBarStyleDefault;
self.navigationController.navigationBar.barStyle = UIBarStyleDefault;
}