2010年4月アーカイブ

Irodoriの1.1版は嬉しいことにUSのitunes storeのNew and noteworthyに載せてもらうことができた。1.1版の特徴は、要望が多かった既にPhotoAlbumに保存してある画像からの解析機能なんだけど、これを実装するときに、わたしとしては初めて同じバージョンのiPhone OSのデバイスの機種間での挙動の違いを体験したので、メモとして書いておこうと思う。

iPhone OSは基本的なアーキテクチャは一貫している印象があって、iPhoneかiPod touchか、OpenGLES2対応かそうでないか、ARM6か7ぐらいかの違いしか無くて、しかも後方互換性があるので、一番ベーシックなところで作っておけばどれでも特に対策をする必要もなく問題なく動くというものだと思っていた。

特に一番基本的なApplication FrameworkであるCocoa touchなんかは上位レイヤーにいるのでどのデバイス用でも同じものを使ってると(そうしない理由があまり浮かばないので)思っていたのだ。

もちろんシミュレータは今までにも違う挙動を示すことがあった。しかし、iPhoneで開発をした方なら分かると思うのだけど、まあ、シミュレータだしな、というところはあった。

さて、問題になったのはUIScrollViewだ。このクラスは表示サイズより大きいものや、複数あるビューを選ぶようなとき、スクロールや拡大縮小機能を提供してくれる。UITableViewはUIScrollViewの派生クラスだ。こういう前置きも必要無いぐらい基本的なクラスだと思う。

このクラスには、中においたコンテンツビューの端に余白を空けるように出来る機能がある。それがcontentInsetで、それぞれに指定したピクセル分端に余白が出来る。コーディングとしては同じ事がUIScrollViewを小さく作っておいてclipsToBoundsをNOにしておくことでも実現できる(clipsToBoundsをNOにするとコンテンツビューがそのサイズでクリップされなくなるので)。

contentInsetを使った方が便利な点はスケールした場合も座標の計算を行わなくても良いという点。コンテンツビューのスケールに依らず指定ピクセル分の余白を空けてくれる。もちろん、スケールに合わせてコンテンツビューサイズを変更すれば同じ事は出来る。

Irodoriでは指定された画像から解析用の画像を切り出すという処理の切り出し部分を指定するところにUIScrollViewを使用した。初期値は縦または横の短い方がちょうど切り出す領域の大きさになるように拡大または縮小している。切り出し領域は画面端よりオフセットされた位置にあり、その上下左右をcontentInsetで指定している。

このスケールされた状態で領域と同じ大きさの場合スクロールはされない。contentInsetの分とスケールされた辺の長さを足したものが丁度UIScrollViewの大きさと同じになるためだ。正方形の場合は固定された状態に(初期的に)なる。

これが期待されるべき動作で、仕様通りでもある。さらにいうとiPhone 3Gの3.1.3ではその通りに動作した。しかしシミュレータでは動作が異なっていた。拡大縮小およびスクロールを繰り返した後、または最初から。そのタイミングは決まったものではなく、突然「外れる」のだ。まさしく、外れると表現するのがいちばんその状態にしっくりと来る。

シミュレータだけの問題なら放っておいても問題ないのだけど、iPod touch 1st gen.で試してみたら、なんとシミュレータと同じ挙動になったのだ(つまり、「外れた」)。バージョンも確かめてみたのだけど3.1.3だった。

つまりは同じバージョンのOS間でAPIの挙動が異なったというわけだ。

こういう時はたいてい非正規な初期化など、どこかミスをしてることが多い。しかし、色々と試してみたけれども、片方はちゃんと動作し続け、もう片方は「外れた」ままだった。

そのものずばりな解決方法があるのかもしれないが、わたしはとりあえず次のように対処しておいた。

  • UIScorollViewDelegate protocolのscrollViewDidEndDragging:willDecelerate:のdecelerateがNOのとき
  • またはscrollViewDidEndDecelerating:が呼ばれたとき
このときにcontentOffsetの値の値が範囲を超えていた場合に範囲内に戻すようにした。contentOffsetプロパティに直接設定しても良いし(setContentOffset:)、setContentOffset:animated:を使用し、戻るところをアニメーションさせることも出来る。アニメーションさせた場合も終了時にDelegateのメソッドscrollViewDidScroll:が呼ばれるので、そこでスクロール中は禁止していた処理を許可状態などにする。

もっともこれが確認できるのは一部の機種に限られるのだけど。

Irodoriの場合、領域切り出し部分なので、仕様通りの動作を期待すると「外れていた」場合、領域外までふくむことになり、最悪の場合BAD_ACCESSで落ちてしまう(そして落ちた)。UIが絡むところはやはりその値がちゃんと想定した範囲内かどうかはチェックした方が良いな、と、再認識したのだった。

申請していたアプリが、今日審査に通ったという通知が届きました。これが前から少し話題に出していたアプリで、カテゴリとしてはカメラアプリになるのだけど、写真を撮る事が目的ではなく、カメラを通してそこにある色をサンプリングしようというのがそのコンセプトです。

アプリケーションの名前は"Irodori"といいます。

使い方は至って簡単で、他のアプリと同じようにツールバー上のカメラアイコンを押すとカメラ画面になります。

ここで撮影をすると、それを解析した特徴色が16色ほどピックアップされるので、その中から気に入った色があればお気に入りマークをつければ、自分のカラーパレットにお気に入りの色が集まっていくという仕組みです。

そうやってピックアップした色見本をメールやtwitpicで家族や友人に見せることも出来ます。

無料のお試し版は出来ることはここまでで、保存できる枚数にも制限があるのですが、アプリ内課金で機能制限解除版を購入していただくと、さらにパレットをAdobe act形式やase形式、PaintShop pal形式でのエクスポートも可能になります。もちろん保存できる枚数の上限も大幅に増えます。

基本機能は無料お試し版で使用可能なので、是非一度お試しください。

再申請したアプリの結果は、今日の時点ではまだ返ってきていない。大体in reviewになってから結果がくるまでに営業日で7日ぐらいかかるようだ。アプリの審査が通ったら、お披露目しようと思うのだけど、また要再提出となると、また一週間ということになって・・・。iPhoneアプリはこのあたりが一番難しいですね。

任天堂やソニーなんかはもっと速いんだけど、審査をする本数も全然違うというのもあるんだろう。そういえば任天堂にはマリオクラブ(いつのまにか会社になっててびっくりした)というのがあり、初めて名前を聞いたときは秘密結社?などと思ったのだけど、ソフトのクォリティコントロールをしているところだ。ここが、OKを出さないとリリースさせてもらえない。ソフトウェア上のバグから、どのロットのハードではちゃんと動かないなどというレポートまで報告してくれる。どのロットのハードでもちゃんと動かないとダメというのが、任天堂は遊べるということには強いこだわりがある会社なんだなという印象をうけた思い出がある。

さて、今回申請したアプリはたくさんの画像を扱うもので、すべてをメモリ上に持っておくことが出来ないので、必要になったらロードしないといけない。とはいえ、いちいち待たされてから、画像の内容を判断するのはもどかしいので、まずは荒くでも見たい。最初に軽いけど荒い画像を表示しておいて、そのうちに隙を見て正式な画像をロードする、つまり遅延読み込み(delayed loading)だ。