この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
以前取り上げましたが、EaselJS v0.6.0 からイベントモデルが変更されています。
EventDispatcher クラスが実装されて、addEventListener や removeEventListener、dispatchEvent 等のメソッドが使えるようになりました。 しかし、Haxe で実装した場合、removeEventListener が正しく動かない場合があるようです。なかなか致命的です。
サンプル
package ;
import createjs.easeljs.EventDispatcher;
import haxe.Log;
class RemoveEventListenerTest extends EventDispatcher {
public function new() {
addEventListener("test", testHandler);
dispatchEvent("test");
dispatchEvent("test");
}
private function testHandler(e:Dynamic):Void {
removeEventListener(e.type, testHandler);
Log.trace(e);
}
}
出力結果
RemoveEventListenerTest.hx:16: {
type : test,
target : [EventDispatcher]
} Boot.hx:45
RemoveEventListenerTest.hx:16: {
type : test,
target : [EventDispatcher]
} Boot.hx:45
上記の例では、最初にイベントが送出された時点で removeEventListener しているはずなのですが、ログが二度出力されてしまいます。
この問題を調査した所、addEventListener や removeEventListener に渡される関数がクラスの prototype にある場合に、Haxe コンパイラによってクロージャでラップされてしまう事が原因のようです。このため、EventDispatcher の持つリスナーオブジェクト内の関数との比較が一致せず、イベントリスナの除去が正しく行われません。
幸い、元の関数とコンテキストへの参照がアクセス可能なので、これらの値を利用して、Haxe でも正しく動作する removeEventListener メソッドを作ってみます。
(function() {
var p = createjs.EventDispatcher.prototype;
p.removeEventListener = function(type, listener) {
var listeners = this._listeners;
if (!listeners) { return; }
var arr = listeners[type];
if (!arr) { return; }
for (var i=0,l=arr.length; i
※2013/06/11追記
また、MouseEvent 等のクラスは、実際には EventDispatcher を直接継承していないので、個別にメソッドを上書きする必要があります。