Titanium Mobile 2.0 対応など

Titanium Mobile がメジャーバージョンアップして SDK が 1.8 から 2.0.1 になりました。HBFav を SDK 2.0.1 に対応させる作業をひとまず終えたので、以下雑感など。

Titanium Mobile 2.0.1 で何が変わったか

大きな変更点はレイアウトシステムの更新です。加えていろいろとバグフィックス。ほかにも Appcelerator Cloud Services (ACS) という BaaS 連携が発表されていますが、純粋に SDK のアップデートというとレイアウトシステムとバグ修正が主なところ。Andorid位置情報対応の強化、Module API のアップデートもありますが、この辺は iOS の開発にしか使っていない自分的にはあまり関係ない。

先日東京で開かれたローンチイベントに参加された方々が要点をまとめてくださっているので、より詳しくは以下のURLを見てください。

レイアウトシステムの更新

このレイアウトシステムの更新が後方互換性という観点ではちょっとしたアップデートで、これまで View の横幅、縦幅を "auto" で指定していたものがそのままだと期待した通りに動作しなくなる。そのかわり Ti.UI.SIZE と Ti.UI.FILL という二つの定数を明示的に使い分けて指定しなさいと、そういうことになりました。要するに、後方互換性がなくなった。

なぜそんな変更を加えたか、最初はパフォーマンス向上のためとかそんな風に聞いていたのですが実際には、iOS と Android 間のクロスプラットフォーム性を向上させるためというのが主眼だった模様です、たぶん。なんで、正直なところ iOS アプリのみに使っている自分のような開発者にはあまり直接的なメリットにはなりません。

具体的にどう修正するべきかは

のドキュメントに詳しく書かれています。最後の段落 "Migrating Applications to Release 2.0" に前バージョンと同じ動きにしたかったら

  • "auto" を指定していた width / height には Ti.UI.SIZE を指定する
  • "auto" も何も指定していなかった width / height で (2positions pins を定義してないところ) は Ti.UI.FILL を指定する

で ok とあるように、基本的にはこの2方針で実装する。自分のアプリも基本的にはこれでほぼうまく動いたのですが、それでも相変わらず WARNING が消えないのと、微調整が必要だったところはそこそこありました。

あとは、まだ未解決なんですが、Ti.UI.SIZE などでシステム側に height を計算させた場合に、文字の折り返しが横幅ぎりぎりまで到達してしまった場合などに縦幅の計算がうまくいってないケースがあるようです。自分のコードの書き方が悪いのかどうかはっきりとは判断がつかないけれども、色々試しても治らないのでおそらく計算処理のバグか何かではないか。

http://dl.dropbox.com/u/2586384/image/20120426_162739.png

こんな風に、途中要らないスペースが空いてしまったり

http://dl.dropbox.com/u/2586384/image/20120426_162811.png

逆に TableViewRow の高さが足りなくて文字が見切れてしまったりする。( teppeisさんに他意はありません(笑) )

結局 Titanium Mobile 2.0 とは・・・

こうして見てみると、1.8 → 2.0 とメジャーバージョンアップ! とは言うものの、実際にはレイアウトシステムの後方互換性が失われるが故にメジャーバージョンアップとしたような印象も受けてしまわないでもないですね。バグ修正は嬉しいけれど。

ACS を使って初めて、2.0 のバージョンアップの恩恵が得られる、そういうメジャーバージョンアップなのかもしれません。

クロスプラットフォームに関して ─ ついでにTitanium Mobile 雑感

レイアウトシステムの更新は、iOS と Android でのプラットフォーム依存な処理を制御しやすくするために行われた変更で、ここからも、Titanium Mobile がクロスプラットフォーム、なるべくひとつのコードあるいは同じやり方で iOS/Android 両対応のアプリが開発できることを推してしていきたいのだという姿勢が伺えます。

個人的には、このアプローチに関して思うところがあります。

同じフレームワークや言語で iOS/Android のアプリどちらも作れる、というところまでは良いです。でも、ワンソースで両者のアプリを作ろうとするのはそもそも無理があるのは、まあ、デベロッパーならみんな良く知っている。

iOS と Android は同じスマートフォンOSで、どちらも一見似たようなルック & フィールを持っているようなところもあるので、かつての Web開発におけるクロスブラウザ対応のようにとりあえず一つ作っておけば OK というのは魅力的に見えるし、そんな風にできるのではないかと思ってしまうのは仕方がない。

Facebook がプロジェクトスパルタンで、それまでフルネイティブアプリとして開発されていた各プラットフォームのアプリを、Embedded Web Views 的なアーキテクチャ ─ PhoneGap や Sencha Touch が目指すような、ネイティブアプリの中の WebView すなわちHTML5でアプリを作れるようにして、ネイティブコードはブリッジして呼び出せるAPIを提供する ─ にしたのも、複数のアプリの開発の手間暇から逃れたい、あるいは Web のようにダイナミックにコンテンツを更新したいという意図からでしょう。以前は、一つ機能を追加するたびに7つのプラットフォームのコードをリリースしなければいけない、と嘆いていたそうですから。

しかしですね、その一見似たようなルック & フィールの iOS と Android は、UI のアーキテクチャが、割と根本的なところで差異があります。Android 開発はほとんど経験がないに等しいので具体的にこう違うと論じることができるほどには理解できていませんが、ナビゲーションのあり方、例えば iOS は UINavigationController を使ってアプリ内部で新しいウィンドウを生成して処理する、つまりウィンドウを密結合させる形で作るのに対し、Android はシステム的には疎な View を生成して両者を単に画面遷移上つながってるとみなす、要はステートレスな Web のような考え方のアーキテクチャになっているとか、複数の項目を選択させるあるいはトグルスイッチの UI の考え方も違えば、ボタンの左右の配置ポリシーも違うとか、結構違うもんです。

この辺、実はオフィシャルのデザインガイドラインにずばり書いてある。

Most developers want to distribute their apps on multiple platforms. As you plan your app for Android, keep in mind that different platforms play by different rules and conventions. Design decisions that make perfect sense on one platform will look and feel misplaced in the context of a different platform. While a "design once, ship anywhere" approach might save you time up-front, you run the very real risk of creating inconsistent apps that alienate users. Consider the following guidelines to avoid the most common traps and pitfalls.

「Android 版をワンソースで同じルック & フィールにして」という方針はそもそもアンチパターンなのだ諸君! ということです。

Appcelerator 的に "Cross Platform" と明示的に言ってるかどうかは、言ってるような言ってないような曖昧なところはありますが、そもそものUIアーキテクチャの異なる二つのシステムを統合しようとするのは筋が悪いと個人的には思うので、あまりそっち方面に力を入れるのではなく、あくまで iOS や Android のアプリを、ネイティブそれよりもより手軽に作れるということにフォーカスして欲しいなとは思います。違うところは違ってていい、どうせワンソースでアプリ作ったりしないから。

iOS の UIKit は "UIKit Framework" という名前が指すように、それそのものがフレームワークであり、フレームワークをさらにフレームワークで抽象化するような Titanium Mobile のようなアプローチはいまいちとする見方をする方もいるようです。まあ確かに言われてみれば、直感的には正しい気もする。ただ、実装上の都合難しいことはあって乗り越えられない壁が出てくることはあるかもしれないけれども、Titanium でイベントドリブンな JavaScript でユーザインタフェースが書けるというのは、使ってみると非常に手に馴染むし悪くないんですね。少なくとも、ユースケースレベルでの抽象化という意味では間違った方向性ではないと思う。繰り返しになりますが、実装レベルでいいかどうかは別として。

そのコア部分が良くできている、つまり Objective-C ネイティブそれで書いたのと遜色ないような出来のものが作れるようであれば、この手の処理系には未来があるなあと自分は思います。

現状は、まだ(あくまで自分が感想を述べられるのは iOS に関してのみですけど) ピュアネイティブと比較した場合には細かいところで少し雑さが見つかる。それほど目立つわけではないけれど、例えば TableView の Row を選択して新しいウィンドウを開く時のフォーカスが、ネイティブの場合は戻ってくるまでフォーカスされているのに、Titanium で作るとそのフォーカスが外れてしまっているとか。ちょっとした動きで画面がチラつく (これは自分がシングルコンテキストモデルで開発していないからかもしれない) というようなことがある。ここのチューニング如何が、今後の Titanium Mobile で長くアプリを開発していけるかどうかの分かれ目ではないかと感じます。

速度に関しては、iPhone 3GS のときは特に TableView 回りの速度がいかんともしがたいものがあって、こりゃネイティブで書き直さないと駄目かなと思っていたものの 4S にしたらほとんど気にならなくなった。Instruments で見ても合格ラインであるところの 40 〜 60FPS は出る。今年中に iPhone 5 は出るという話だし今後もスマートフォンの性能はムーアの法則的に上昇していくのは間違いない、というかそここそが今計算機界隈のフロンティアであるので、ここはもうある程度開き直ってしまっても良い頃合いなのかもしれないですね。

そのほかパッチ

2.0.1 になりましたが、例によって build ディレクトリ内に生成された Objective-C のコードに少しパッチを当てて使っています。

変更点としては

  • UILabel の背景の透過処理をなくして Instruments で見た時の Blended Layer を消せるように (TiUILabel.m)
  • WebView の背景の透過処理をなくして同情 (TiUIWebView.m)
  • 画像の余計なリサイズ処理をスキップして、リサイズ時のオフスクリーンレンダリングが発生しないように (UIImage+Resize.m)
  • 2.0.1 の WebView のローディングインジケータはバグがある (左上隅っこに表示されて見切れている) ので、インジケータを表示しないで js 側で自前で用意するように (TiUIWebView.m)

という4点です。

あと、自分は Titanium Studio は使っておらず TiDev Community を使ってビルドしてます。こちら SDK 2.0.1 でも問題なく使えました。

まとめ

ごちゃごちゃと脈絡なく書きました。要するに、Titanium Mobile には期待していますが、まだ本当に本格的なアプリを作るのには若干手が届かずというところなので中の人には是非ともがんばって欲しいなあと思っていると、そういうことです。上から目線ですみません。応援しています。