# Titanium Mobileの暗黒ノウハウを公開します。 _published: 2011/03/04_ ![alt](http://b.hatena.ne.jp/entry/image/http://d.hatena.ne.jp/shunsuk/20110304/1299229674) WEB+DB PRESS Vol.61の特集は、Titaniumでした。実際にアプリを作りながらのチュートリアルになっています。正統派な入門記事です。 でも。期待してた内容ではありませんでした。私は、Titaniumの暗黒面が知りたいのです。いつものWEB+DB PRESSなら、そんな記事が多いのですが、さすがにまだ開発者が少なそうなTitaniumではアッサリ目に仕上げるしかないのでしょう。そこで、このどうでもいいブログで、Titaniumのバッドノウハウ、いや、暗黒ノウハウをメモっておきます。 アプリを1本開発しただけですので、そこまでTitaniumのことを解っているわけではありません。間違っているところなどがありましたら、指摘してもらえるとありがたいです。暗黒ノウハウをみんなで共有しましょう。あと、スシなどをおごってもらえると、もっとありがたいです。 ## 前提。 Titaniumのバージョンは、主に1.5.1です。途中で1.6.0がリリースされたので、状況は変わっているかもしれません。目の前の状況は、刻一刻と変わるものです。現状に甘んじてはいけません。あと、私が作ったのはiPadアプリです。Androidは試してません。 - [TitaniumでiPhoneアプリとAndroidアプリを同時に作ったよ。 - このブログは証明できない。](http://d.hatena.ne.jp/shunsuk/20101203/1291380711)[![alt](http://b.hatena.ne.jp/entry/image/http://d.hatena.ne.jp/shunsuk/20101203/1291380711)](http://b.hatena.ne.jp/entry/http://d.hatena.ne.jp/shunsuk/20101203/1291380711) ## 読み方。 Titaniumの読み方ですが、「チタニウム」ではなくて、「タイタニウム」だそうです。オシャレに「タイタニューム」と読んでもいいかもしれませんね。私は「藤岡弘、」と読んでます。 ## ビルドできない。 最初に試した頃にTARGET_BUILD_DIRのエラーが出ていました。今は大人になったので、出ていません。もし出たら、プロジェクトの設定をいじると直ります。 - [TitaniumでiPhoneアプリをビルドするとTARGET_BUILD_DIRのエラーが出るとき。 - このブログは証明できない。](http://d.hatena.ne.jp/shunsuk/20101214/1292326102)[![alt](http://b.hatena.ne.jp/entry/image/http://d.hatena.ne.jp/shunsuk/20101214/1292326102)](http://b.hatena.ne.jp/entry/http://d.hatena.ne.jp/shunsuk/20101214/1292326102) 最近はまったく再現しないので、私も大人になったんだと思います。 ## シミュレーターが起動しない。 エラーが発生したり反応がなくなったりしてシミュレーターが起動しない場合は、再度「Launch」ボタンをクリックしてください。「Launch」が有効で「Stop」が無効になっている場合は、いくら待ってもシミュレーターが起動しないケースが多いです。また、いったん「Stop」して「Launch」しなければならない場合もあります。 私に話しかけても反応が無いときがありますが、再度話しかけると反応します。 ## アプリのアイコン。 Titanium Developerでアプリのアイコンのファイル名を変更できます。このとき、存在するファイル名を書く必要があります。むしろ、設定を変えずに、Project/Resources/iphone/appicon.pngファイルを上書きするといいですね。 現在のTitaniumだと、アイコンやDefault.pngがうまく適用されなくて、イライラする日々を過ごすこともあるかもしれません。そんなときは、このサイトを見てください。 - [Nekostagram - ねこ大好き専用Instagram](http://nekostagram.heroku.com/) ## Application IDに使えない文字。 net.shunsuk.MyAppのようなApplication IDには、ハイフンが使えません。ドメイン名にハイフンを使っている人は、残念でした。Objective-Cで作る場合はハイフンもOKなのですが、Androidのパッケージ名で使えないっぽいです。 あと、試してないですが、Application IDには絵文字も使えないかもしれません。 ## 使ってはいけないフォルダ名。 公式ドキュメントに載っているのかどうか分かりませんが、使ってはいけないフォルダ名があります。プロジェクトを作ると生成されるResourcesフォルダの下に、contentsフォルダとかresourcesフォルダとかを作ってはいけません。知らんかったら、トラップ以外の何者でもありません。 - [Titaniumでcontentsという名前のフォルダを作ってはいけない罠。 - このブログは証明できない。](http://d.hatena.ne.jp/shunsuk/20110216/1297862770) システムフォルダの中にエロ画像フォルダを作るのも、相手によっては逆効果だと思います。 ## なぜかエラーが起こる。 何の問題もないはずなのに、エラーが起こる場合があります。信じられないかもしれません。私も信じられません。でも本当です。しかも、エラー内容が表示されずに、スタックトレースが表示されます。どうしようもありません。試されてます。この場合は、Project/build/iphoneフォルダ以下をのファイルをすべて削除して、再度実行するとOKです。ちなみに、iphoneフォルダを消すと、デバッグできなくなりますので注意してください。 Titaniumはオープンソースなので、なぜエラーが起こるのか解析して、パッチを送ってあげるといいですね。私もオープンなのですが、心を開いていないと言われることが多いです。 ## tiapp.xmlを直接編集。 基本的なことは、Titanium Developerで設定できます。もっと細かい設定をしたければ、プロジェクトのフォルダのtiapp.xmlを編集する必要があります。このへんの設定は、よく使うんじゃないでしょうか。 - statusbar-style - statusbar-hidden - orientations tiappって、なんて読むんでしょうね。血アップ。 ## TitaniumはTiと省略可能。 APIの話です。Titaniumは、Tiと省略することができます。なので、下のどちらでもOKです。 - `Titanium.UI.createView();` - `Ti.UI.createView();` 原子番号22。チタン族元素の一つで、金属光沢を持つ遷移元素です。 ## 実機転送。 作ったアプリを実機に転送する場合、Titanium Developerから転送しようとすると下のような手順になります。 - ビルドされる。 - iTunesに登録される。 - iTunesとiPhoneを同期する。 面倒なので、生成されたプロジェクトをXCodeで直接開いて実行する方が速いです。Project/build/iPhoneフォルダにプロジェクトファイルがあります。ただ、そのままでは動かない場合があるので、プロジェクトの設定を適宜変更してください。また、XCodeから実行することで、パフォーマンスツールを利用することもできます。 ビルドにはとても時間がかかります。不要なライブラリを削除すればいい気もしますが、そのへんは調べてません。不要なものを削除していって、結局自分も不要なんじゃないか、という疑問に達した人は、そんなことないよ!! ## AdHocビルド。 AdHocビルドするには、上で書いたように、プロジェクトファイルをXCodeで開いてビルドすると簡単です。プロジェクトにdist.plistなどを追加して、プロジェクトの設定をいじってください。 今日の弁当には、アドホックに玉子焼きがついてました。 ## includeの順番。 Objective-Cの#importと根本的に違います。LLのrequireのように、コードが展開されます。この時、includeの順番に注意しましょう。 ```js Ti.include('A.js'); Ti.include('B.js'); ``` こう書くと、~~AからBは見えますが、BからAは見えません~~。 追記(2011-03-21):書き間違えてました。BからAは見えますが、AからBは見えません。 includeに関しては、こちらも参考に。 - [TitaniumのインクルードパスをResourcesからの相対パスで指定する方法 | ひげろぐ](http://higelog.brassworks.jp/?p=1130) 今日の弁当のハンバーグには、チーズがインクルードされていました。 ## フォントサイズ。 UI部品のフォントサイズを動的に変えたいとき。 ```js textView.font.fontSize = 36; ``` では変りません。font自体を設定します。 ```js textView.font = { fontFamily:'Helvetica Neue', fontSize:36 }; ``` フォントにつらくなってきました。 ## Objectの生成。 ObjectやArrayを生成するとき。 ```js ver o = new Object() ver a = new Array() ``` こう書くと、警告が出ます。リテラルを使いましょう。 ```js ver o = {}; ver a = []; ``` これって、JavaScript的な意味があるのでしょうか。そもそも、生きる意味などあるのでしょうか。 ## 子Viewのサイズ。 子Viewのサイズを指定していなければ、親Viewの中で最大表示されます。この状態で親Viewのサイズを変えると、連動して子Viewのサイズが変わります。ここで、子Viewのサイズをピクセルで指定していると、連動しなくなるので注意してください。 Titaniumでは、サイズをパーセント指定できます。うまくやれば、マルチプラットフォームに仕上げられますね。でも、なかなか難しいと思うんです。ロジックだけを共有して、UIは切り分けた方がいいと思います。 私の子も、親の私に連動して、背が低いです。 ## jQuery。 JavaScriptのライブラリを使えるというのもTitaniumの特徴です。ですが、jQueryはそのままでは動きません。wondowやdocumentなどのオブジェクトがないためです。無理やりjQueryを使うには、こちらの記事を参考にしてください。 - [TitaniumでjQueryを使う | ひげろぐ](http://higelog.brassworks.jp/?p=1148) ただ、DOMがないので、jQueryを使うメリットがあるのかは微妙です。ちなみに、JQはジェットスター航空の航空会社コードです。紹介したので、サービスしてください。 - [航空券 予約・購入・運賃案内|Jetstar - ジェットスター](http://www.jetstar.com/jp/ja/index.aspx) ## アニメーション。 Titaniumは、アニメーションがやりやすいです。MogSnapというアプリがTitanium製らしいですが、アニメーションが楽しいアプリになっています。 - [もぐもぐエンターテイメント系Twitterクライアント MogSnap ~We Love Mogmog!~](http://mogsnap.jp/) アニメーションをガンガン使いたいのですが、いろんなタイミングに注意しましょう。例えば、下のコードではmessageWinがcloseするのは500ms後ですので、それまでにmessageWinが閉じられていることを前提としたコードが走るとマズイですね。まあ、これは分かりやすいケースですが。 ```js messageWin.close({opacity:0, duration: 500}); ``` 私もMogSnapを使っていますが、コンビニおにぎりかマクドナルドかカップ麺なので、使う機会がありません。ちょっと不健康な食生活ですね。健康のため、カップ麺はドラッグストアで買ってます。 ## 画像のロードとリロード。 ImageViewは、createImageViewでimageを設定しても、そのタイミングでは画像をロードしません。親Viewにaddしたりして表示されるタイミングで画像をロードします。これは、iOSのUIImageViewと挙動が違うので注意が必要です。 また、ImageViewがremoveされても、すぐに画像がリリースされません。キャッシュしてるっぽいですが、詳しくは調べていません。そのImageViewを使う予定がなければ、サイズの小さい画像をimageにセットすることでメモリを節約しています。ホントはやり方があるかもしれませんが。 メモリ管理の必要がないところが、メリットでもあり、デメリットでもありますね。記憶を管理して、黒歴史を消し去りたいですね。マインドアサシン。 ## ScrollViewの謎挙動。 ScrollViewにImageViewを乗せて画像をズームします。ズームした状態で、関係ないWindowを開きます。そして、Windowを閉じます。すると、ScrollView上のImageViewの位置がおかしくなるという謎挙動に遭遇しました。今のところ、原因不明です。 私もよく、原因不明の物欲に駆られて、原因不明のアマゾンで、原因不明の買い物をします。 ## クロージャ。 クロージャを使わないと、思ったように動作しないケースがあります。ファイルを分割して、コンテキストが別になった場合などで必要になるんでしょうか。知らんけど。クロージャに慣れていない人は、復習しておいたほうがいいかもしれません。 ```js var label = Ti.[UI](http://d.hatena.ne.jp/keyword/UI).createLabel(); view.layout = (function() { var l = label; return function(message) { l.text = message; }; })(); ``` そんなに、くろーじゃないよ。って言いたかっただけです。 ## ちょっと。 コードスニペットを。イマイチなのも公開しときます。 デバッグするときにTi.API.info("デバッグ!")と書くのが面倒なので、utility.js的なファイルに下のコードを書いてapp.jsの先頭でincludeしておきます。 ```js var info = Ti.API.info; ``` そうすると、こう書けます。 ```js info("デバッグ!"); ``` 完璧グローバルですが、この場合はいいんじゃないかと思います。 clickイベントをハンドルする場合、こう書きます。 ```js button.addEventListener('click', function(e) { info("clicked"); }); ``` これも、utility.jsにこう書いておくと。 ```js Object.prototype.click = function(handler) { var sender = this; this.addEventListener('click', function(e) { handler(sender, e); }); }; ``` こう書けるようになります。 ```js button.click(function(sender, e) { info("clicked"); }); ``` 完全に好みの問題なので、なにか便利になるわけではありません。Object.prototyeを汚染してますし、senderなんてなくてもe.sourceでOKですし、いろいろ腑に落ちないところはあります。でも、button.clickって書きたいんです。おすすめじゃないですが、いちおう書いておきました。 最後に、これもutility.jsに書いておきます。 ```js var getImageFile = function(name) { return Ti.Filesystem.getFile(Ti.Filesystem.resourcesDirectory, 'images/' + name); }; ``` そうすると、imagesフォルダに入ってる画像を短いコードで呼び出せます。 ```js imageView.image = getImageFile('profile.png'); ``` ## フレームワーク。 JavaScriptでAIRアプリを作った時も思ったのですが、画面遷移まわりなど、薄いフレームワークを作ったほうがよさそうです。ガチガチのフレームワークは必要ないのですが、JavaScriptは柔軟性が高い分、統制がとれなくなる可能性が高いので。 まあ、柔軟性が低い上に統制もとれてない私に比べれば、たいした問題ではありません。 役に立つかどうかわかりませんが、いろいろ書いてみました。「間違っているところがあるかもしれません」と書いて逃げるのは好きではないのですが、間違っているところがあるかもしれませんのでご注意ください。 たくさん書いたので、スシが食べたいです。