2014年12月22日月曜日

今年のTitanium向けに書いた記事まとめとアプリ紹介2014版

Titanium Advent Calendar 2014の22日目。今年自分が書いた記事のTitaniumに関するまとめ。

まず今年の革命的だった発見が2つ。

 

1つ目がアイコンフォント。

各デバイスごとに大きさの違う画像を切り出していたのがなくなった。色違いや大きさが違う場合もコードで指定するだけでいい。メモリ効率もいいらしい。

 

2つ目がthisとparentの存在。

これで無駄にグローバル領域やクロージャ(無名関数)を使わない書き方が出来るようになった。入れ子にならないのでコードが読みやすい。

 

 

そして、これらを発見する前だけど今年の初めに作ったアプリを紹介。

teniteoというママ向けのSNSサービスのクライアントアプリ。

本家のアプリ(Android, iOS)とは別に実験的なアプリ。ゲストでも閲覧できるのと学園のイメージを取り入れてみた。

appicon


技術的な特徴

  • Titanium SDK 3.2.0.GA
  • iPhone, Androidで同じ見た目。ソースコードは分けてない。必要なときだけif文で分岐している。
  • Alloyは使ってない
  • ListViewをかなり頑張っている
  • サーバーはNode.jsでWordPressのデータベースに接続

こんなListView。

device-2014-12-16-165206 device-2014-12-16-165411

コメントもListViewを使ってる。PCで投稿されたコメントの中に表示できないバグがある。。。

device-2014-12-16-165441 device-2014-12-16-165918

本当はもっと美少女ゲームっぽくしたかった。自分のデザインセンスのなさを痛感(キャラクターはデザイナーさんにお願いした)。

ゲストでも閲覧だけなら使えるので試したい方はどうぞ。サーバーでこのアプリ向けには3つのプロセスしか待ち受けしてないので遅く感じるかも。

 

来年は今作っているのも含めていくつかサービスを公開予定。

Titanium的にはSocket.IOと連携したリアルタイム性を重視したアプリを作りたい。

では、みなさん良いお年を。明日のTitanium Advent Calendarはcoeさんです。

 

< Related Posts >

2014年12月18日木曜日

開発中のTitanium SDKをInstallして試す

titanium_beta_install今起きている現象が開発バージョンで直っているかインストールして試してみたときの覚書。

環境: Mac OS X 10.10.1, Xcode 6.1.1, Titanium SDK 3.4.1.GA

最新のダウンロード先の一覧は下記から。

この時点で最新の3.5.0 BETAをダウンロードしてインストール。コマンドで全部やってくれる。

$ ti sdk install http://builds.appcelerator.com/mobile/3.5.0/mobilesdk-3.5.0.Beta-osx.zip

確認してSDKの切り替え
$ ti sdk
$ ti sdk select 3.5.0.Beta

切り替えた後はビルドする前にクリーンするのを忘れずに。
$ ti clean

 

< Related Posts >

2014年12月15日月曜日

TitaniumとWordPressで(比較的)簡単SNSアプリ

titanium_wordpressTitanium Advent Calendar 2014の15日目。Titanium + WordPress + Node.jsの環境がうまくいっているので紹介。

書いてる途中で簡単か?と思い直し「比較的」付けた(笑

慣れると
WordPressで公開している → アプリ作りましょうか?
まずはアプリでサービス提供 → Web版も提供
が短期間で出来るようになる。

長くなったのでポイントだけ。

 

WordPressを使う理由

  • データベースの構造がシンプルで汎用性がある
  • 標準でユーザー管理、投稿、コメントなどの基本機能が揃ってる
  • テーマやプラグインで本体に手を加えずに開発出来るのもいい
  • アクション・フィルターの機能がNode.jsからキックするのに便利
  • 重い処理や非同期処理したい場合はWP-CRONの仕組みが便利
  • 情報が豊富
  • 初心者でもWordPressは触った人が多いので教えなくて済む。
    → アプリ側を上級者で開発して、Web側は他人に振れる。
  • PHPフレームワークと比べて遅いけど、最近は負荷分散する仕組みが豊富なので許容範囲になる。
    → アプリのリクエストはNode.jsで処理するのでWordPress(PHP)の遅さは関係なくなる

 

 

Titaniumを使う理由

  • 一つのコードでAndroid, iOS両対応出来るのが強い
  • ネイティブとまでいかなくてもサクサク動く
  • 最悪ネイティブモジュールを作れば何とかなる
  • Node.jsと組み合わせときの開発効率がうまい(全部JavaScript)

 

Node.jsを使う理由

  • アプリからは同時に大量のリクエストが来るのでPHPでは捌き切れない
    → データベースはMySQLではなくスレッドプールが使えるMariaDBにする
  • TitaniumもJavaScript。CommonJSの考え方を理解してTitanium側のコード品質も上がっていく。
    → Titaniumで作った汎用関数がそのままNode.jsで使える

 

ちなみにWordPressは外部にAPIを提供しているので、アプリから直接WordPressにリクエストを送るだけでも大抵のことが出来る。

Node.jsのモジュールの中にはWordPressのXML-RPC APIに接続するのもある。

私は最初アプリ向けのAPIはWordPressのプラグインで実装したけど、遅すぎて耐えられなかった。そのときの記事がこれ。

 

Node.jsから直接SQL実行するのが一番というのが私の結論。

Node.jsでアプリのAPIを実装するときのポイント。WordPressとどう連携するか。

  • ユーザーのログイン、新規登録だけNode.jsからPHPコマンドを実行(wp_insert_userとか)
  • データの取得、登録はNode.jsからSQL文を発行する。
    → そうしないと速度的に耐えられない。
    → カテゴリーの登録だけちょっと苦戦するぐらいで後は難しくない。
  • WordPressのアクションを実行する汎用的なPHPを書いてNode.jsからアクション名を引数にキックすると便利。
  • メール送信とかはWordPress側(プラグイン)で実装しておくと、ウェブ版を実装したときに楽。
    → Node.jsからはアクション名でキック
  • ファイルアップロードもNode.js側でファイルの配置とDBにInsertして、あとの画像加工はアクション名からWordPress側(プラグイン)で実行する
  • PHPシリアライズされたデータでもphpjs使えばエンコード、デコード出来る
  • WordPress側でオブジェクトキャッシュを有効にしていると、直接SQLでアップデートしたデータがウェブ版に反映されない。
    → キャッシュをクリアするアクションをAPIから発行する必要あり

 

WordPress公式アプリはソースコードが公開されているので参考になるかもしれない。

GPLなのでコードを流用する場合はソースコードを公開しないといけない。便利な機能はTitaniumのモジュール用に切り出して公開するとみんなが幸せになれるかも。

 

PhoneGap + WordPressで考えている人も後でPhoneGapの限界ともっさり感で泣くより、CommonJS覚えてTitaniumで開発するのをオススメしたい。

 

明日のTitanium Advent Calendarはk0sukeyさんです。

 

< Related Posts >

2014年12月10日水曜日

【Titanium】Alloy vs Classic

titanium_alloy_vs_classic2年前にAlloyを試してみたけど、未だにClassicな書き方をしている私。そろそろAlloyも成熟してきたころだと思い調査したときの覚書。

環境:Titanium SDK 3.3.0.GA

私がクラシックな書き方をしている理由(言い訳)を考えてみた。

  • Alloyも結局クラシックなコードに変換している。だったら最初からクラシックな書き方でいいと思う
  • WEB開発で複数言語(PHP, HTML, CSS, JavaScript)から開放されたと思ったのに、やっぱりXMLとかCSSっぽいのを書かないといけないの?
  • CommonJSの考え方でサーバー側(NodeJS)とクライアント側(Titanium)をJavaScriptで書いているのが気持ちいい
  • Alloyにバグがあったら見つけるのも直すのも大変そう(まだAlloyを信用できない)
  • クラシックだとひとつの画面はひとつのJavaScriptファイルで完結するので管理しやすい
  • 今作っているアプリはサーバーと連携するクライアントアプリ。ビジネスロジックは全部サーバー側にあるので、MVCでいうところのViewをTitaniumで開発している感覚。さらにMVCで開発するほど大規模なアプリは今のところない。
  • 自分の中で確立した書き方から脱却するのが億劫

 

世間ではAlloyで開発するべきだという意見が一般的。

ベストアンサーを日本語訳してみた

  • Alloyは一般的な方法と統一したコードを提供する。これは他のAlloyプロジェクトの開発者や新規開発者が理解するのに容易。
  • Alloyは便利で役に立つたくさんのレイアウトショートカットを提供しているので、より早く開発することが出来る。我々のセールスチームは70%のコードを削減できた。これはたぶんベストな例だけど、Alloyアプリでたくさんのコード削減できる。
  • Alloyアプリは各プラットフォームに最適なコードと追加ツールを提供するのでクラシックなアプリよりも動作が速い。
  • Alloyは横長のアプリを作ったり、テーマを作ったり、再利用するコンポーネントを作るのに便利。これらはクラシックコードだと別々なカスタムソリューションが必要となる。
  • AlloyはMVCの原則に従って均一なコードを書くのを手助けしてくれる。これは前述したように開発をスピードアップする。しかもメンテナンスしやすいコードを書くのも手助けしてくれるため、トータルコストを削減する。そしてそういうコードはバグも少ない。
  • Alloyは一貫したディレクトリ構造を提供する。この構造はプロジェクト間でも変わらないし、入れ替わる開発者にとっても一貫したもの。
  • ほとんどのサンプルアプリやドキュメントはAlloyから先に作られる。ほとんどの新しいコミュニティで開発されるコンポーネントはAlloyのウィジェット。クラシック指向のコードではない。
  • 全ての拡張モジュールはクラシックなプロジェクトでも使える

 

全くスキがない。

今度新しいアプリを作るときはAlloyを使おうと思ってきた。

 

< Related Posts >

2014年12月8日月曜日

【Titanium】thisとparentとchildrenを使った書き方

Titanium Advent Calendar 2014の8日目。最近多用しているthis, parent, childrenを使った書き方の紹介です。

環境: Titanium SDK 3.3.0.GA

Alloyは使ってません。

これらを使うとループの中でクロージャ(無名関数)を作成する必要がなくなったり、「引数を使いまわしたいから無名関数でネストする」必要がなくなります。

メモリ効率的にもいいような気がします(実際は分かりません)。

例えばこんなコードがあったとします。

/ui/common/testView.js

// Expose API
exports.createView = createView;

function createView(title) {
    var frameView, buttonView, i;

    frameView = Ti.UI.createView({
        layout: 'vertical',
        height: Ti.UI.SIZE
    });

    for (i = 0; i < 10; i++) {
        buttonView = Ti.UI.createButton({
            title: title + i
        });

        (function() {
            var index = i;
            buttonView.addEventListener('click', function() {
                alert(index);
            });
        })();

        frameView.add(buttonView);
    }

    return frameView;
}

これを呼び出すapp.js

var win = Ti.UI.createWindow({
    backgroundColor:'#ffffff'
});

win.add(require('/ui/common/testView').createView('ボタン'));
win.open();

これを実行すると10個のボタンを配置します。それぞれクリックすると何番目のボタンがクリックされたかalertします。

iOS Simulator Screen shot Dec 7, 2014, 1.52.43 PM

何も問題なく動きますが、クロージャの中で宣言されたindexはメモリから開放されないようです。

なのでクロージャを使わない書き方にしてみます。childrenを参照すればbuttonViewも使わなくて済みます。Clickしたあとの処理も外に出します。

/ui/common/testView.js

// Expose API
exports.createView = createView;

function createView(title) {
    var frameView, i;

    frameView = Ti.UI.createView({
        layout: 'vertical',
        height: Ti.UI.SIZE
    });

    for (i = 0; i < 10; i++) {
        frameView.add(Ti.UI.createButton({
            title: title + i
        }));

        frameView.children[i].dataIndex = i;
        frameView.children[i].addEventListener('click', handleClick);
    }

    return frameView;
}

function handleClick(e) {
    alert(e.source.dataIndex);
}

 

これでネストするクロージャがなくなってスッキリしました。

次はモジュールとして使いやすくするために引数を追加して処理を分けてみます。

app.jsはこんな感じで呼び出します。

var win = Ti.UI.createWindow({
    layout: 'vertical',
    backgroundColor:'#ffffff'
});

win.add(require('/ui/common/testView').createView({
    title: '上のボタングループ',
    frameColor: '#faa'
}));

win.add(require('/ui/common/testView').createView({
    title: '下のボタングループ',
    frameColor: '#aaf'
}));

win.open();

 

testView側ではparentを参照して、呼び出されたときの値を参照するようにします。

あと、for文の中で追加するviewが複雑になったときのためにe.sourceを参照せずthisを使うようにします。

/ui/common/testView.js

// Expose API
exports.createView = createView;

function createView(args) {
    var frameView, i;

    frameView = Ti.UI.createView({
        layout: 'vertical',
        backgroundColor: args.frameColor,
        height: Ti.UI.SIZE
    });

    // Save to custom property
    frameView.viewData = args || {};

    for (i = 0; i < 10; i++) {
        frameView.add(Ti.UI.createButton({
            title: args.title + i
        }));

        // Save to custom property
        frameView.children[i].dataIndex = i;
        frameView.children[i].addEventListener('click', handleClick);
    }

    return frameView;
}

function handleClick() {
    var data = this.parent.viewData;
    alert(data.title + ':' + data.frameColor + ':' + this.dataIndex);
}

実行結果

iOS Simulator Screen shot Dec 7, 2014, 2.35.44 PM

こんな感じで無名関数をネストせずに書いていくことが出来ます。Androidでも問題なく動きます。

addEventListenerは自動でthisをセットしてくれますが、JavaScriptのcallメソッドを使うと自分でthisをセットして関数を呼び出すことが出来ます。

 

thisやparentはviewが複雑化したときに威力を発揮します。

実体験ではカレンダーの月表示を実装したときは、thisとparentとカスタムプロパティを使ってコードがスッキリしました。

一応今までのアプリは上手く行ってますが、懸念点としては

  • parentプロパティは公式ドキュメントに載ってないので、そのうち使えなくなるかもしれない
  • view自体に値を保存するやり方はいいのかな?
  • 実際にメモリ効率よくなるの?
  • Alloy使えばヨロシクやってくれるのかな?

 

あくまでも私はこう書いているよということで。「自分はこう書いてるよ」というコメント大歓迎です。

 

< Related Posts >

Related Posts Plugin for WordPress, Blogger...

Blog Archives