この記事は、@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 さんお願いします。