小さな Titanium Mobile の読み物

The Little Book on Titanium (Appcelerator Titanium)

JavaScript を使って iOS/Android などマルチプラットフォーム対応のネイティブアプリケーションを構築することができる Appcelerator Titanium についてまとめた非公式サイトです。

ページ1 | はじめに

  1. Appcelerator Titanium
  2. Write Once, Adapt Anywhere
  3. 使えるの?
  4. 苦手なものは何?

ページ2 | 開発ツール

  1. Titanium Studio
  2. Titanium CLI

ページ3 | 開発スタイル

  1. JavaScript
  2. Titanium Classic
  3. Alloy

ページ4 | アプリケーションの例

  1. プロジェクトを作る
  2. レイアウトを考える
  3. 土台を作る
  4. 細かい機能を実装していく
  5. 終わりに

ページ5 | Titanium を拡張する

  1. モジュール
  2. Titanium Cloud Services
  3. altJS

開発スタイル

JavaScript

Titanium は JavaScript を使ってアプリケーションのコードを書きます。 JavaScript は Web アプリケーションで開発ではもはや当たり前に使われるプログラミング言語になりました。 Titanium アプリケーションの開発では Web アプリケーション開発とは異なる JavaScript の書き方が存在します。 Titanium はむしろ Node.js に近い開発スタイルを取ります。

CommonJS Modules

Titanium は CommonJS Modules の規格を元に実装されています。 Web ブラウザで動作させる JavaScript はファイル単位でプログラムコードを分割しますが、 Titanium では exports (module)require という命令を使ってもう少し賢くプログラムコードを分割する手法が提供されています。

module.js
// 関数をモジュールとして公開する
exports.myFunc1 = function () {
    alert("This function is myFunc1.");
};
// プライベートな関数
function myFunc2() {
    alert("This function is myFunc2.");
}
app.js
var module = require("module");
module.myFunc1();  // This function is myFunc1.
module.myFunc2();  // Undefined

例えば modules.jsapp.js があるとします。 app.js の中では require という関数を使って module.js を読み込んでいます (拡張子は必要ありません) 。このとき、 module.js の exports 命令を使って登録された関数 myFunc1 はモジュールとして公開されるので、 app.js の中から呼び出すことができます。一方、公開されていない myFunc2 は app.js の中から呼び出すことができません。

CommonJS Modules を使うことでプログラムコードを管理しやすく分割することができます。

Titanium Classic

Titanium Classic とは Titanium 1.x の頃から使われている開発手法です。 Titanium プロジェクトの基点である app.js を元に、 CommonJS Modules を使ってコードを適切に分割し、プログラムを組み上げていく手法です。

Titanium Classic では UI を構成するコード、ロジックを構成するコード、ユーザの操作を処理するコードなど、アプリケーションを開発する上で必要なコードは全て JavaScript で記述し、ファイルの中に混在した状態になります。

app.js
// ウィンドウを作る
var win = Ti.UI.createWindow({
    backgroundColor: "#FFFFFF"  // 背景色は白にする
});
// ボタンを作る
var button = Ti.UI.createButton({
    title: "ボタン"  // ボタンに表示する文字は「ボタン」にする
});
// ボタンを押したときの処理を書く
button.addEventListener("click", function () {
    // アラートを表示する
    alert("ボタンを押しました");
});
// ウィンドウの上にボタンを乗せる
win.add(button);
// ウィンドウを開く
win.open();

Titanium Classic は Titanium アプリケーション開発を行う際に学習するべき手法です。規模が大きくなってくる前に CommonJS Modules を使ってコードを適切に分割して管理する方法を覚えたり、 Titanium が提供している API を知るためには欠かせません。この手法を覚えることで、以下で紹介する Alloy が生きてきます。

実際のアプリケーションを開発する際には Titanium Classic ではなく、 Alloy の利用が良いでしょう。

Alloy

Alloy は Titanium の為に作られた公式 MVC フレームワーク です。 Alloy を使うことで プログラムコードを Model, View, Controller に分離して管理することで効率よくプロジェクトを管理することができます。 Alloy では、

を使います。例えば、上述のウィンドウの上にボタンを配置し、ボタンを押したときにアラートを表示するようなプログラムは以下のように記述します。

Model
定義なし
View | XML
<Alloy>
  <Window>
    <Button id="my_button" title="ボタン">
  </Window>
</Alloy>
View | TSS
"Window": {
    backgroundColor: "#FFFFFF"
}
Controller
$.my_button.addEventListener("click", function () {
    alert("ボタンを押しました");
});

Alloy は XML を使って UI を定義し、 TSS を使って装飾し、 JavaScript を使ってロジックを記述します。 HTML / CSS / JavaScript の関係に近いものがあります。 XML を使って UI を構造的に記述できるため、 UI の親子関係を明確にすることができます。また、共通する UI パーツ毎に ID や Class を使って TSS を使って装飾することもできるため、 UI の変更にも対応しやすくなるでしょう。

Model の例

Titanium Classic では SQLite を使ってデータベースに情報を保存する場合、プログラムコードの中に SQL 文を記述する必要があります。 Alloy では Model に用意された SQL アダプタを使うことで SQL を書くことなく SQLite に情報を保存することができます。

Model の定義

Model の定義は Titanium Studio では GUI または、コマンドラインから行います。

Titanium Studio を使ったモデルの定義

alloy generate model user sql name:text age:integer gender:text

Model

exports.definition = {
    config: {
        columns: {
            "name": "text",
            "age": "integer",
            "gender": "text"
        },
        adapter: {
            type: "sql",
            collection_name: "user"
        }
    },
    extendModel: function (Model) {
        _.extend(Model.prototype, {
            // Model を保存するときに整合性を確かめる処理を書く
            validate: function () {
                // ここで整合性を確かめる
                return true;
            }
        });
        return Model;
    },
    extendCollection: function (Collection) {
        _.extend(Collection.prototype, {
            // extended functions and properties go here
        });
        return Collection;
    }
}
Controller
/**
 * モデルを定義してデータベースに保存する
 * set メソッドと呼び出すと、 Model で定義した validate 処理が自動的に実行される
 * また、 isValid メソッドで validate 処理を明示的に呼び出すことができる
 */

// ユーザーモデルのオブジェクトを作る
var user = Alloy.createModel("user");

// ユーザーモデルにプロパティをセットする
user.set({
    user: "ジョン",
    age: 3,
    gender: "male"
});

// ユーザーモデルの validate 処理を呼び出す
if (user.isValid()) {
    // データベースに保存する
    user.save();
} else {
    alert("ユーザ情報が不正です");
}

Controller 側では Model に用意された処理を呼び出すことに終始することで、ユーザからの入力の処理や分岐に集中することができます。 Model 側では情報の整合性チェックや加工に集中させることで、 UI とロジックの分離を促します。

その他の機能

Alloy には、複数の Alloy を使った Titanium アプリケーションで使い回しが効く Alloy 向けのモジュールである Widget やアニメーション効果などの組み込み機能が多数用意されています。1からコードを書かずに用意された機能を組み合わせるだけでもリッチな効果が得られたり、開発効率を向上させたりすることができます。