Titanium mobile でやってはいけないTi.App.addEventListener

2012/11/06

この記事は、@astronaughtsさん主催のTitanium mobile “early” Advent Calendar 2012に参加して書いております。6日目(11/6)担当でございます。

やってはいけないTi.App.addEventListener

addEventListenerをTi.Appに設定する場合、

Ti.App.addEventListener("save_astronaughts",function(){
Ti.App.info("I'll save you!!");
});

な感じで書きます。
が、注意しなければならないのは、この処理が複数回呼ばれるような場所にあると、呼ばれるたびにeventが追加されてしまいます。同じイベント名だからといって上書きされません。

私にも、windowをopenしてcloseしたらそのwindow内で定義したevent全て消えてくれるのかと思ってた時期がありました。。。
前の日の記事でもaddEventListenerについて書かれていますが、

var win = Ti.UI.createWindow({});
win.addEventListener("save_astronaughts",function(){
Ti.App.info("I'll save you!!");
});

これだとwinをcloseすればOKですが、Ti.Appだとグローバルに定義している形になり、残ってしまうようですね。

複数定義してしまってても、アプリ自体はすんなり動いたりするので、見落としてました。

二重登録の対策

もちろん、複数呼ばれる場所に書かない、というのが基本ですが、私の場合、もう書いてしまって定義場所を移動しづらかったので、ラッパーを作って対策してみました。


    // Ti.App.addEventListener の二重登録防止関数
    Ti.App.ael = function(listener_name,callback){
        // 登録済みの場合追加しない
        if(Ti.App.in_array(listener_name,Ti.App.listeners)){
            return false;
        }
        // イベントを配列に登録
        Ti.App.listeners.push(listener_name);
        
        // イベント追加
        return Ti.App.addEventListener(listener_name, callback);
    }

定義済みのイベント名をグローバルな配列listenersに登録して、定義済みかのチェックを行っています。コード内のin_arrayはこちら。何かの公開コード(忘れた。。。)に定義されていたのを拝借しております。

Ti.App.in_array = function(needle, haystack, argStrict) {
    var key = '',
        strict = !! argStrict;
 
    if (strict) {
        for (key in haystack) {
            if (haystack[key] === needle) {
                return true;
            }
        }
    } else {
        for (key in haystack) {
            if (haystack[key] == needle) {
                return true;
            }
        }
    }
 
    return false;
}

何かもっと素敵な対策方法あれば教えてください!

次は

@daoki2 さんお願いします。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です