удалить слушателя, который имеет анонимную функцию в Actionscript 3 - PullRequest
10 голосов
/ 06 января 2010
up.addEventListener(MouseEvent.CLICK, 
    function clickFunc(event:MouseEvent):void
    { 
        revealSpinner(event,51.42,1,spinner);
        event.currentTarget.removeEventListener(event.type, arguments.callee);
        autoTimer.stop();
    },
    false, 0, true);
down.addEventListener(MouseEvent.CLICK, 
    function clickFunc(event:MouseEvent):void
    { 
        revealSpinner(event,51.42,-1,spinner);
        event.currentTarget.removeEventListener(event.type, arguments.callee);
        autoTimer.stop();
    },
    false, 0, true);

Приведенный выше код добавляет слушателя к паре MC. Первоначально методы были анонимными, но я назвал их clickFunc (), чтобы попробовать ссылаться на них в моем приемнике удаления.

Вот мой код удаления слушателя. Оба эти фрагмента находятся в отдельных функциях. Метод add listener вызывается перед методом remove.

up.removeEventListener(MouseEvent.CLICK, clickFunc );
down.removeEventListener(MouseEvent.CLICK, clickFunc);

Как только я публикую фильм, я получаю эту ошибку:

1120: Access of undefined property clickFunc.

Ответы [ 5 ]

5 голосов
/ 14 января 2010

Прежде всего, у вас есть одно и то же имя, используемое дважды (clickFunc), невозможно определить, какое имя вы указали в своих вызовах для удаленияEventListener. Во-вторых, clickFunc будет доступен только в той функции, в которой он объявлен:

function foo() {
    var clickFunc: Function;
    up.addEventListener(MouseEvent.CLICK, 
        clickFunc = function (event:MouseEvent):void
        { 
            revealSpinner(event,51.42,1,spinner);
            event.currentTarget.removeEventListener(event.type, arguments.callee);
            autoTimer.stop();
        },
        false, 0, true);

    // 'clickFunc' available here, so this is possible:
    up.removeEventListener(MouseEvent.CLICK, clickFunc);
}

function bar() {
    // 'clickFunc' is not available here, so this is not possible:
    up.removeEventListener(MouseEvent.CLICK, clickFunc);
    // 1120: Access of undefined property clickFunc
}

Если вам нужно сослаться на методы (например, удалить их из события), они не могут быть анонимными. Если вам нужно ссылаться на них из нескольких методов, то они не должны быть локальными для одного метода (foo в приведенном выше примере). И им нужны разные идентификаторы (clickFunc1 и clickFunc2, если хотите). Это мое предлагаемое решение:

private function addHandlers(): void
{
    up.addEventListener(MouseEvent.CLICK, upClickHandler, false, 0, true);
    down.addEventListener(MouseEvent.CLICK, downClickHandler, false, 0, true);
}

private function removeHandlers(): void
{
    up.removeEventListener(MouseEvent.CLICK, upClickHandler);
    down.removeEventListener(MouseEvent.CLICK, downClickHandler);
}

private function upClickHandler(event:MouseEvent):void
{ 
    revealSpinner(event,51.42,1,spinner);
    event.currentTarget.removeEventListener(event.type, arguments.callee);
    autoTimer.stop();
}

private function downClickHandler(event:MouseEvent):void
{ 
    revealSpinner(event,51.42,-1,spinner);
    event.currentTarget.removeEventListener(event.type, arguments.callee);
    autoTimer.stop();
}

Конечно, если, как в вашем примере, методы идентичны, вы можете использовать только один:

private function addHandlers(): void
{
    up.addEventListener(MouseEvent.CLICK, clickHandler, false, 0, true);
    down.addEventListener(MouseEvent.CLICK, clickHandler, false, 0, true);
}

private function removeHandlers(): void
{
    up.removeEventListener(MouseEvent.CLICK, clickHandler);
    down.removeEventListener(MouseEvent.CLICK, clickHandler);
}

private function clickHandler(event:MouseEvent):void
{ 
    revealSpinner(event,51.42,-1,spinner);
    event.currentTarget.removeEventListener(event.type, arguments.callee);
    autoTimer.stop();
}
3 голосов
/ 04 августа 2010

хорошо, есть несколько способов сделать это. вот первый способ, который я думаю, это то, что вы ищете.

var upAnon:Function;
var downAnon:Function;

up.addEventListener(MouseEvent.CLICK, 
    upAnon = function (event:MouseEvent):void
    { 
        revealSpinner(event,51.42,1,spinner);
        event.currentTarget.removeEventListener(event.type, arguments.callee);
        autoTimer.stop();
    },
    false, 0, true);
down.addEventListener(MouseEvent.CLICK, 
    downAnon = function (event:MouseEvent):void
    { 
        revealSpinner(event,51.42,-1,spinner);
        event.currentTarget.removeEventListener(event.type, arguments.callee);
        autoTimer.stop();
    },
    false, 0, true);

up.removeEventListener(MouseEvent.CLICK, upAnon);
down.removeEventListener(MouseEvent.CLICK, downAnon);

и вот еще один способ получить тот же желаемый эффект и функциональность, что и первый. просто чище и обычно стандартная практика.

function upFunction(event.MouseEvent):void {
    revealSpinner(event,51.42,1,spinner);
    event.currentTarget.removeEventListener(event.type, arguments.callee);
    autoTimer.stop();
}
function downFunction(event.MouseEvent):void {
    revealSpinner(event,51.42,-1,spinner);
    event.currentTarget.removeEventListener(event.type, arguments.callee);
    autoTimer.stop();
}

up.addEventListener(MouseEvent.CLICK, upFunction, false, 0, true);
down.addEventListener(MouseEvent.CLICK, downFunction, false, 0, true);

up.removeEventListener(MouseEvent.CLICK, upFunction);
down.removeEventListener(MouseEvent.CLICK, downFunction);

Причина, по которой вы бы использовали первый тип, заключается в том, что вы создавали eventHandler внутри функции и вам нужно использовать переменные, определенные в этой функции, внутри вашей анонимной функции. например, здесь я обращаюсь к var countMe внутри функции anon и увеличиваю его при mouse_down, и он будет увеличиваться до тех пор, пока не будет активирован mouse_up. поэтому каждый раз, когда я нажимаю вниз, он будет отсчитывать от 0 до тех пор, пока мышь не будет нажата, а затем начнется заново.

var anonFunc:Function;

function doThisStuff(event:MouseEvent):void {
    var countMe = 0;

    stage.addEventListener(Event.ENTER_FRAME,
        anonFunc = function (e:Event) {
            countMe++;
            trace(countMe);
        }
    );  
}

function stopCounting(event:MouseEvent):void {
    stage.removeEventListener(Event.ENTER_FRAME, anonFunc);
}

stage.addEventListener(MouseEvent.MOUSE_DOWN, doThisStuff);
stage.addEventListener(MouseEvent.MOUSE_UP, stopCounting);
2 голосов
/ 20 августа 2010

Вы создаете обработчики событий со слабыми ссылками (передавая true для этого последнего параметра). Как вы, вероятно, уже знаете, слабая ссылка не помешает сборщику мусора собирать вашу функцию. Однако, если вы не сохраните ссылку на свои обработчики событий вне области функции, в которой вы их определяете (не похоже, что вы есть), обработчики будут иметь только одну слабую ссылку, чтобы поддерживать их, так что сборщик мусора работает, ваши обработчики все равно ушли. Суть в том, что ваши обработчики событий не выглядят так, как будто они будут запускаться после запуска сборки мусора, поэтому беспокоиться об удалении обработчиков несколько бессмысленно. Они уйдут сами по себе, хотите вы того или нет.

Вам нужно будет сохранить ссылку на эти обработчики событий в области, которая все еще будет существовать, когда они должны запускаться. Как только вы это сделаете, вы сможете использовать эти ссылки для их удаления.

2 голосов
/ 06 января 2010

Это должно сработать ... просто удалите имя метода ...

 up.addEventListener(MouseEvent.CLICK, 
        function(event:MouseEvent):void
        { 
            revealSpinner(event,51.42,1,spinner);
            event.currentTarget.removeEventListener(event.type, arguments.callee);
            autoTimer.stop();
        },
        false, 0, true);
    down.addEventListener(MouseEvent.CLICK, 
        function(event:MouseEvent):void
        { 
            revealSpinner(event,51.42,-1,spinner);
            event.currentTarget.removeEventListener(event.type, arguments.callee);
            autoTimer.stop();
        },
        false, 0, true);
0 голосов
/ 06 января 2010

попробуйте это:

up.addEventListener(MouseEvent.CLICK, 
    clickFunc = function(event:MouseEvent):void
    { 
        revealSpinner(event,51.42,1,spinner);
        event.currentTarget.removeEventListener(event.type, arguments.callee);
        autoTimer.stop();
    },
    false, 0, true);

down.addEventListener(MouseEvent.CLICK, 
    clickFunc = function(event:MouseEvent):void
    { 
        revealSpinner(event,51.42,-1,spinner);
        event.currentTarget.removeEventListener(event.type, arguments.callee);
        autoTimer.stop();
    },
    false, 0, true);
...