imthinker::net

ふらふらうぇぶろぐ

Titanium もくもく会 Tokyo #5 に行ってきました

2013年最初の Titanium もくもく会 Tokyo が 2013/01/25 に開催されました。今回は CyberAgent 様のご厚意で会場を提供していただきました。ありがとうございます。

さて、もくもく会とは銘打ってましたが最初から最後まで LT 大会になってしまいました。しかも半分ぐらいが Alloy に関してというのだから皆さん合金好きですね。私も作っているサービスと Alloy の Tips をお話ししてきましたので LT をメインにご報告をば。

t32k さん : 開発環境について

t32k さんの開発環境についての LT 。 Web デベロッパとして CyberAgent で活躍されていて、 Titanium 3.0 になったら本気出すと言ってしまった以上やるということで開発環境を Sublime Text 2 と Grunt で作りましょうという内容。

Sublime Text 2 に Titanium Mobile に対応したコード補完を付けたり、 grunt-scandium という予め設定しておいたビルドオプション (JSON で記述) を使って Titanium CLI を呼び出したり、ファイルをウォッチして特定のファイルが更新されたら自動でビルドするなどの処理を行えるという素晴らしいサポートツールを作りましたというお話でした。

grunt-scandium は是非とも使おうと思います。

ahomu さん : en.ja OSS でたのしいえいご

ahomu さんの OSS 風ドキュメント翻訳プロジェクトのご紹介。 Alloy の中はその実 Backbone.js と underscore.js の影響が大きく、依存しているのですが、それはつまり、公開されている Alloy のドキュメントだけでは Alloy を使い切ることはできず、 Backbone.js や underscore.js のドキュメントを読む必要があります。

しかし、これらのドキュメントは英語で書かれていますし、英語のドキュメントを読むことになれているはずの技術者 (偏見) であっても、やっぱり慣れた母国語のドキュメントで読みたいはずです。

en.ja プロジェクトでは GitHub を使って OSS 的に Pull Request の仕組みを使ってドキュメントを翻訳するという素晴らしい活動を行っており、 Backbone.js と underscore.js のドキュメントはほぼ翻訳できているという素晴らしい報告がありました。

実は私も Backbone.js のドキュメントを最近はこちらの翻訳物を参照させていただいています。やる気さえあれば誰でも参加可能だそうです!

hamasyou さん : Alloy について

hamasyou さんの Alloy で作っている毎日のお弁当に感謝するための素敵なアプリ紹介と Alloy のべた褒め LT。 Alloy を使うことで Android 版でも動くものが案外すんなり作れたそうです。 Android と Titanium は茨の道を歩むための第一歩ですが、 Alloy がうまいこと吸収してくれているのでしょう。

そして Alloy の残念なところで紹介されていた Collections.fetch メソッドが全件取得という問題に対する解答として、 GitHub で公開されている sqlx アダプタを使うと WHERE 句 などが使えて便利というお話がありました。これは是非とも使いたいですね。

ryugoo_ : HERE & Alloy Tips

私の LT 。今、 HERE というサービスを作っています。とにかく簡単に Twitter のアカウントを教え合うためのサービスです。まずは Twitter で、あとから Facebook や LINE などに対応できれば良いのかなと思っていますが、何はともあれ Twitter 。サービスについてはスライドをご覧ください。

Alloy Tips は XML と JavaScript をそれぞれ Jade と CoffeeScript に置き換えて書くためのビルド時フックである jmk を書くと便利という話と、 Alloy 自体の便利なところのお話をしました。段々と便利になってきています。 HERE はもうちょっとで公開です。

DENSO : アプリコンテストと車のセンサーを使った Titanium 製アプリ

株式会社デンソーさんからはアプリコンテストのお話と Titanium と車のセンサー情報を組み合わせたデモアプリが紹介されました。実際にこの場に車を持ってくるわけには行かないので、アプリ開発者に提供されているシミュレータを使ってセンサー情報を再現し、それを Titanium に組み込んだモジュールを使って取り込むというデモが行われました。

車の情報を表示させるとか、その情報を使って手元の端末で何かを引き起こせるとか、ダイナミックですよね。男の子の夢です。そんなデンソーさんが提供する SmartTech Award ではデンソーさんが提供するモジュールを組み合わせた Titanium 製アプリのための Titanium 賞があります。興味、ご関心のある方は是非ともご参加ください!

kaz_konno さん : ユーザ会からのお知らせ

Titanium Mobile ユーザ会で渉外担当を務められる kaz_konno さんからは様々なお知らせがありました。主に来月16日に開催される tiTokyo です。 tiTokyo は Appcelerator 社初の海外カンファレンスで、 Mini CodeStrong と言ってもおかしくないレベルのイベントになりそうです。事前質問は日本語 / 英語のどちらでも受け付けていて、フォームはこちらから

yagi_ さん : ユーザ会サポート掲示板と tiTokyo LT に関して

Titanium Mobile ユーザ会長である yagi_ さんからはユーザ会サポート掲示板では正しく Markdown でコードを書いてねというお知らせと、本決まりではないけども tiTokyo で30秒ぐらいでアプリの紹介 LT やる機会があるかもと言うご案内。

```javascript
var hoge = function () {
    return "huga";
};
```

JavaScript のシンタックスハイライトを有効にするために、そしてコードを正しく表記するにはこのような Markdown を書きます。すると、

var hoge = function () {
    return "huga";
};

このように美しくハイライトされますし、コードも意図したとおりに表示されるはずです。夜な夜な表記を修正する yagi_ さんの為にも、皆様掲示板ご利用の際はご協力をお願い申し上げます。

h5y1m141 さん : 中規模アプリ開発について

Qiita アプリを開発されている h5y1m141 さんの LT 。 GitHub で OSS として公開されている TiQiita アプリですが、この開発の裏話がありました。デザインパターンや MVC 的なコードの分割、そしてアプリのテスト (Jasmine) など、実践的な内容でした。

underscore.js と moment.js を使っていて、特に moment.js に関しては

このように仰っています。また、 h5y1m141 さんが勤められているパソナテック様にセミナーなどに興味があって登録をされると、オライリーの書籍を割引で購入できるそうです。 JavaScript 第6版などは厚くて高いので、良いチャンスかもしれませんね。

k0sukey さん : tiTokyo アプリの紹介

TiPlatformConnect や TiIconicFont で知られる k0sukey さんからは tiTokyo のためのアプリを Alloy で作りましたというお話。アプリは GitHub に公開されているのですが、恐らくは現在最高の Alloy デモアプリケーションなのではないでしょうか!?

今ならソースコード中にキチンとコメントを書いて Pull Request を投げるだけでもアプリの開発者欄に名前が載るそうですよ (笑) … Alloy では Widget がとにかく便利で使っているそうです。あとは Builtins にある moment.js や Dialog ですね。 Dialog は OK やキャンセルボタンのあるダイアログを簡単に作ることができるラッパーで、面倒くささの回避に活躍します。こうした便利機能が予め用意されているのも Alloy の良いところですね。

t_sugie さん : Titanium Mobile 製アプリの紹介

Titanium Mobile でアプリを開発される t_sugie さんからは Android 苦労話と TiStoreKit についての苦労話がありました。 Android に関しては方々で語られているとおり、 Titanium で開発する場合は茨の道です。バージョンの差、端末の差にもろに影響されますし、 Java オンリーで開発する場合にも苦労する点に加えて Titanium 独自の問題が出てきてしまいます。

また、 TiStoreKit を使ってアプリ内課金の仕組みを作っても、うまく動作しない部分があるとかで、もっとオフィシャルに課金部分も Titanium から便利に使える仕組みがあったら良いのになと思いました。

終わりに

これを書いている時点で今日は Titanium 新年会です。もくもく会冒頭に Lanica Inc. の Kota Iguchi さんがお話ししたのですが、 Platino 開発の裏話などが聞けそうです。私も参加しますし、参加登録者数が20名を超えたおかげで貸し切りになるということで、 LT 開催も予定されています。

というわけで、寝て起きたらネタを絞り出して LT に備えます (`・ω・´) ……

:(;゙゚'ω゚'):

CODESTRONG!

いつの間にか Alloy が進化していました

Titanium Mobile 用の公式 MVC フレームワークである Alloy 。発表当時は本当に使い物になるのか、継続的に開発は続くのか、 Appcelerator 的にはどのような立ち位置になるのかなどなど、不明な点が多かったのですが、何だかんだで便利に使えている製品です。

そんな Alloy ですが、どうしてもこれまで納得ができない仕様が1つありました。それは、 View である XML に onClick イベントハンドラを仕込む場合は Controller 側の関数は「文」でなければダメという点です。

今回、 Alloy 0.3.4 を改めて見直してみると、改善が見られました。

経緯

JavaScript でよく使われる関数の定義方法は大まかに2つあります。1つが関数宣言文。もう1つが関数リテラル (lambda 式) です。

function hoge() {
    alert("関数宣言文");
}

var huga = function () {
    alert("関数リテラル");
};

どちらもよく使う関数の定義方法なのですが、関数宣言文にはホイスティングという機構が働きます。

hoge();

function hoge() {
    alert("関数宣言文");
}

関数の呼び出し命令の後に書かれた関数宣言文は、実行時には関数が存在しているスコープの先頭にまで「巻き上げられて」実行ができるというものです。これは関数リテラルではダメです。

var huga;

huga();  // huga is undefined

huga = function () {
    alert("関数リテラル");
};

もしも関数リテラルを使って関数を定義した場合に、先に関数の呼び出し命令を書いたならばこのような形で評価されてしまいます。これらが災いして、 Alloy では関数リテラルで定義した関数は View 側に記述した onClick からは呼び出すことができませんでした。

// Alloy が出力するコントローラのコード例
function Controller() {
    // 1. Alloy が出力するユーティリティコード群
    // 2. Alloy の View (XML+TSS) を Titanium API を呼び出す形に整形されたコード
    // 3. View で設定された onClick イベントハンドラ
    // 4. ユーザが書いた Controller のコード
    // 5. Alloy が出力するユーティリティコード群 その2
}

Alloy はこのようなコードを出力します。イベントハンドラは関数の名前を引数にとるため、関数リテラルで関数を書いてしまうとイベント登録時には、まだ関数が入っているはずの変数は undefined ということになってしまうのです。

Alloy 0.3.4 による改善

これに対して、 Alloy 0.3.4 を試してみたところ、関数リテラルで関数を定義した場合でも、 onClick イベントが正常に動作するようになりました。 Alloy が出力するコードに何らかの変化があったようです。

// Alloy 0.3.4 が出力するコントローラのコード例
function Controller() {
    // 1. Alloy が出力するユーティリティコード群
    var __defers = {};
    // 2. Alloy の View (XML+TSS) を Titanium API を呼び出す形に整形されたコード
    // 3. View で設定された onClick イベントハンドラ
    foobar ? $.__views.__alloyId1.on("click", foobar) : __defers["$.__views.alloyId1!click!foobar"] != 0;
    // 4. ユーザが書いた Controller のコード
    var foobar = function () {
        alert("__defers オブジェクトによって延滞登録");
    };
    __defers["$.__views.alloyId1!click!foobar"] && $.__views.__alloyId1.on("click", foobar);
    // 5. Alloy が出力するユーティリティコード群 その2
}

ちょっと見てみると、このようなコードを出力していました。この例では foobar が falsy だった場合は __defers オブジェクトに対応する名前のプロパティで値は true (!0) を取り、ユーザが実際に書いたコードの下で改めてイベントの登録を行っています。

この変更によってユーザが Controller に関数宣言文や関数リテラルを意識することなく書けるようになりました。

何が嬉しいのか? それは CoffeeScript 。

この変更の利益を最も享受できるのは、 CoffeeScript を使って Titanium Mobile を楽しんでいるユーザです。

hoge = ->
  alert "CoffeeScript の関数は全てリテラル"

CoffeeScript で関数を定義すると、 JavaScript に変換された後は全て関数リテラルになります。この仕様によって CoffeeScript で Alloy のコードを書く場合は、

# インライン JavaScript
`function hoge() {
     alert("せっかく Coffee を使っているのにこれはかっこ悪い");
}`

このようにインライン JavaScript を使わないと View 側に書いた onClick イベントハンドラが動作しませんでした。しかし、 Alloy 0.3.4 の __defers オブジェクトを使った延滞登録によって CoffeeScript で書いたコードがそのまま動作するようになりました。

Alloy をビルドするときに CoffeeScript を JavaScript にトランスレートするフックスクリプトに関しては @k0sukey さんのブログをご覧ください。

CODESTRONG!

tiTokyo (Appc 主催 Ti カンファレンス) が開かれます

開催告知お手伝いです。 2013/2/13 にベルサール六本木で株式会社デンソー協賛、 Appcelerator 社主催の Titanium Mobile カンファレンスが開催されます。 Appcelerator 社がアメリカ以外でカンファレンスを主催するのは日本初!

会場には CEO Jeff Haynie 氏や Appcelerator 社のコアエンジニアの方々が来日予定で、今後の Titanium を取り巻く製品やソリューションについての展望が聞けると思います。

また、デンソー社からは Titanium とカーナビや車のセンサー情報を連携させるためのソリューション紹介、 Lanica 社からは Titanium Mobile 用のゲームエンジンとして開発が進められている Platino エンジンについて、 Lanica 社共同設立者兼アーキテクトの井口氏から直接お話が伺える予定になっています。

朝から夜までみっちりと1日 Titanium 漬けになれるカンファレンスです。なんと、昼食や閉会後の懇親会の参加費は無料 ! 参加しない手はありません。

詳細に関してはイベント告知ページをご覧ください。
また、イベント参加登録は ATND からどうぞ!

CODESTRONG!

Titanium で TableViewRow 長押しイベント

最近の TableView を使った iOS アプリは Row を長押しすると何らかのアクションを実行できるものが多いです。 Sparrow は未読 / 既読 のフラグ切り替えができますし、 NewsStorm はアクションを選択するためのメニューが表示されます。

しかし、 Titanium Mobile でこれを実現しようと思っても longpress や longtap イベントは用意されていません。 touchstart / touchend / touchcancel を組み合わせると何とかできそうですが…。今回は長押しイベントを再現してみましょう。

下ごしらえ

まずは TableView が乗っかったひな形を用意します。ファイル名は app.js で。

/*jslint devel: true */
/*global Titanium */
(function (Ti) {
    "use strict";
    var win, table, row, i, l, data;
    win = Ti.UI.createWindow({
        backgroundColor: "#FFFFFF"
    });
    table = Ti.UI.createTableView({
        data: []
    });
    for (i = 0, l = 10, data = []; i < l; i += 1) {
        row = Ti.UI.createTableViewRow({
            title: "TableView #" + i
        });
        data.push(row);
    }
    table.data = data;
    win.add(table);
    win.open();
}(Titanium));

これで10個の Row を持つ TableView が載ったアプリができあがりました。

イベント処理

次に、 TableViewRow に長押しイベントをくっつけていきます。 JavaScript は {} がブロックスコープを提供しないので、 for や while の中で作った要素にイベントを持たせるときは注意が必要です。 app.js を改造してみましょう。

/*jslint devel: true */
/*global Titanium */
(function (Ti) {
    "use strict";
    var win, table, row, i, l, data, press;
    win = Ti.UI.createWindow({
        backgroundColor: "#FFFFFF"
    });
    table = Ti.UI.createTableView({
        data: []
    });
    function longPress(row) {
        return function () {
            press = true;
            setTimeout(function () {
                if (press) {
                    row.backgroundColor = "#FFFFFF";
                    console.log(row.title);
                    press = false;
                }
            }, 500);
        };
    }
    function cancelPress() {
        press = false;
    }
    for (i = 0, l = 10, data = []; i < l; i += 1) {
        row = Ti.UI.createTableViewRow({
            title: "TableView #" + i,
            backgroundColor: "#FFFFFF"
        });
        row.addEventListener("touchstart", longPress(row));
        row.addEventListener("touchmove", cancelPress);
        row.addEventListener("touchend", cancelPress);
        data.push(row);
    }
    table.data = data;
    win.add(table);
    win.open();
}(Titanium));

こんな感じになりました。 row には touchstart / touchmove / touchend イベントを設定しています。 touchmove / touchend は同じ関数 (cancelPress) が呼び出されます。

問題は touchstart イベントです。定義時に row を引数に longPress 関数を実行して、関数を返却してもらっています。返却してもらった関数だけ抜き出すと、

function () {
    press = true;
    setTimeout(function () {
        if (press) {
            row.backgroundColor = "#FFFFFF";
            console.log(row.title);
            press = false;
        }
    }, 500);
}

こうです。中では setTimeout を使って 500ms 遅延させて関数を実行させています。このとき、 press の値が true だったら row の長押しにヒモづけたい処理が走るわけです。指が動いたり、タップを止めれば cancelPress 関数によって press の値は false になります。

この例では 500ms の間 row を長押ししていれば console.log によって受け取っていた row.title がコンソール上に記録されるはずです。

row.backgroundColor の謎

さて、 if (press) の直下に row.backgroundColor = "#FFFFFF"; があります。 Titanium Mobile 自体のバグなのか、仕様なのか分かりませんが、 row の背景色を変化させると touchstart イベントをキャンセルできます

もしも背景色を変化させないと、いつまでたっても row を押しっぱなしになってしまいます。正直、黒魔術だと思いますが、これで長押しイベントを再現することができました。

Titanium 2.1.x からこの状態は続いていて、 3.0 でどうなるのか様子を見ていましたが、 3.0.0.GA でも Continuous Builds (3.1.x) でも同じように動くことから、しばらくは大丈夫そうだなということで公開します :-)

CODESTRONG!

新年 Titanium イベントのお知らせ

2013年も始まったばかりですが、 Titanium Mobile のイベントが開催されます。

  1. Titanium もくもく会 Tokyo #5
    サイバーエージェントさんに会場を提供していただいて開催予定です。すでにキャンセル待ちの状態ですが、これまでのもくもく会を考えると参加できる可能性は高いと思います。
  2. Titanium 新年会 2013
    Titanium もくもく会 Tokyo #5 の翌日に開催される新年会です。私も参加しますが、参加予定メンバーはどの方も Titanium の濃い話ができる方ばかりです。 Platino ゲームエンジンの話とか、かなり突っ込んだ話が聞けてしまうかもしれませんよ。

2012年はユーザ会も立ち上がり、 年末には Titanium 3.0 もリリースされ、 Command Line Interface や Alloy MVC Framework など、様々な動きがあった年でした。プラットフォームは順調に進化していますが、イマイチ名前と信頼感が広がっていない閉塞感も感じました。

2013年はユーザ会のサポート掲示板や、 FAQ の充実など、日本国内でもさらに安心して使える環境になっていくのではないかという期待と、実現に向けた活動の年だと思います。1 Titanium Mobile ファンとして、今年も宜しくお願い申し上げます。

CODESTRONG!

Titanium FAQ 蓄積サイトを立ち上げました

Titanium Mobile ユーザ会のコンテンツの一環として、 Titanium Mobile に関する良くある質問と回答をまとめた FAQ サイトを立ち上げました。

サイトは一般閲覧用の Titanium FAQ と、投稿・編集・削除が可能な Titanium Mobile FAQ Stocker の2つがあります。 FAQ Stocker は Twitter アカウントでログインすることで FAQ の投稿や編集、削除が可能です。

一般閲覧用の Titanium FAQ は @yagi_ さんが管理されていますが、 Titanium Mobile FAQ Stocker の情報と同期しています。 Titanium Mobile をお使いの方で、こんな質問は良くありそうだなと思う物があれば、是非とも Stocker に投稿してください。