Titanium で iPhone開発を始めるときに気をつけておきたいこと7つ
こんにちは、亀本です。
本当は今日はアシアルの日常を書く、という名目のブログ当番なんですが、どうせエンジニアの日常なんてコード書いてますよね。
ということで、最近使ってみたTitaniumについて書いてみる事にしました。
さて、最近ちまたでTitanium Mobileがあつい!という話が出ていて、入門記事もいろんなところで上がり始めていますね。
Titaniumをご存じない方のために簡単に説明しておくと、JavaScriptを使ってiPhone/Androidアプリを作ってしまおう、という物です。
果たしてどんなもんか!と、手元で作成中だったアプリをTitaniumを使って再実装してみたのですが、世間で言われるとおり所々で凝った事をしづらいものの、想像していたよりはずっと、リッチ・簡単・高速に作れる印象でした。
早い、安い、うまいなんてぎゅうどn(ry
その開発の際に、Objective-Cで実装していたときに比べて、「おっ?」と思うところがいくつかあったので、開発時に突っかからないように、気になったポイントをまとめてみました。
多分、当たり前の事も書いてある気もしますが、何か足しになれば幸いです。
なお、僕もTitaniumは初心者の域を脱していないので、おかしなところやよりよい方法がありましたら、がんがん突っ込みお願いします!
1. Ti.include()を過信しない
Ti.include()は外部のJSを組み込める、非常に便利なメソッドです。
ですが、これを過信してしまうと痛い目を見る事があるので、盲目的にならずに挙動に気をつけて使いましょう。
元来JavaScriptにはincludeが存在しないので、この関数の存在をみたときには狂喜乱舞したものです(※やや誇張表現が含まれます)。
が、この関数はC言語の#includeなどと同じで、Ti.include()を呼んだ位置に、呼び出したファイルの内容がそのまま展開されるような挙動を示します。
このとき、特に問題になりやすいのが、include対象となるJSファイルの中で、さらに外部のファイルを呼んでいる場合です。
先ほども書いたとおり、Ti.include()では呼び出した内容がそのまま展開されるので、呼び出されたファイル内でcreateWindow()やcreateImageView()などを呼んで、urlやimageを相対パスで指定していたり、同ファイル内で再度Ti.include()していたりすると、それらのパスが相対パスのまま展開されてしまいます。
そのため、呼び出すファイルのフォルダ階層が異なっていると、それらのファイルの読み込みエラーとなってしまいます。
app.js
tabs.js
main_windows/user.js
main_windows/login.js
というようなファイル群があって、tabs.jsの中で
var useWin = Ti.UI.createWindow({
url:'main_windows/user.js'
});
という処理があった場合、app.jsからtabs.jsをincludeした場合には、正常にuser.jsが呼び出せます。
しかし、ここでlogin.jsからtabs.jsをincludeした場合、login.jsはmain_windows/フォルダの中にいるので、上記の処理では main_windows/main_windows/user.js を呼び出そうとしてしまい、エラーとなってしまいます。
この点は、開発の設計時に気をつけておかないと、ファイルを分割してincludeする前提で作っていたのに、実装してみたらエラーになって方針変更を迫られる事になります。十分注意しましょう。
※なお、imageなどのリソースファイルに限って言うと、絶対パスを指定する事で回避は可能です。
リソースファイルの格納先のパスがTi.Filesystem.resourcesDirectoryに保持されているので、これを使います。
JSファイルは、残念ながらこの指定は通用しないようです。。。
2. TableViewでセクションを作る場合のプログラミングスタイルが大きく違う
これは、Objective-Cでの開発に慣れている人からすると、一瞬戸惑うところです。
(ただ、個人的にはこの方がすっきりする設計だと感じています。)
iPhone開発をしたことある方はよくご存じだと思いますが、TableViewは以下のような構造をしています。
TableView(本体) -> 複数のsection -> section毎に複数のRow
しかし、それにも関わらず、Objective-Cを使った開発ではTableViewのSectionの描画、Rowの描画が共にTableViewのdelgateメソッドとして実装されており、それらが順次呼び出される形で描画されます。
そのため、実装の流れを考える時には、イメージ的にはSectionもCellもフラットに取り扱う印象があり、各行はTableViewオブジェクトに直接配置するイメージ、Sectionのヘッダーなどは、その間に差し込んでいるイメージで開発していきます。(ここは人によって違うかもしれません)
TableView -> Section
-> Row
-> Row
-> Row
-> Section
-> Row
.....
一方、TitaniumではTableViewSectionというオブジェクトが存在し、TableViewとRowの間に挟まるので、
TableView -> TableViewSection -> TableViewRow
-> TableViewRow
-> TableViewRow
-> TableViewSection -> TableViewRow
-> TableViewRow
-> TableViewRow
.......
という、本来あるべきオブジェクトの構造を持たせて実装していきます。
流れを紹介すると、下記のサンプルのようになります。
var win = Ti.UI.currentWindow;
var sections = [];
// first section
var section1 =