Remove ENTER_FRAME EventListener from inside this as3

This is my code in Flash / AS3, in the main class.

addEventListener(Event.ENTER_FRAME,function(e:Event){

        if(findObject == true){
            // I want to remove this ENTER FRAME
        }

});

      

+3


source to share


5 answers


try this:



e.currentTarget.removeEventListener(e.type, arguments.callee)

      

+13


source


  • You shouldn't be doing what you are doing in the above code.

  • The mgraph code has a tiny chance of not working as advertised unless currentTarget

    events have a method removeEventListener()

    (possibly, but very unlikely). From a compiler's point of view, though you will be trying to resolve a method dynamically on an error prone shared object and should be handled with care. This is dangerous because it shows that the programmer "did not know" which object he expected to process and was working on guesswork. Assumptions are great for finding a solution, but equally bad for implementing it.

If you decide to optimize something in your way, then just FYI actually creates a unique (redundant) name in the symbol table (in the compiled SWF file), which leads to degraded SWF compression.

If you're doing this as an experiment, that's fine, but you should avoid this code in real projects.

One more thing to be aware of: comparison with a constant true

is 100% useless. If such a comparison makes sense at all (i.e., findObject

can evaluate to false

at any time), then the if (findObject) { ... }

equivalent but shorter version of your code is. The latter, hopefully the anonymous function has no return type declaration. This won't change much in your example, except that you get a compiler warning. Omitting a type declaration is generally bad style.

EDIT

public function addEventListener(type:String, listener:Function ...):void
{
    this._listeners[type].push(listener);
}

public function dispatchEvent(event:Event):void
{
    for each (var listener:Function in this._listeners[event.type])
        listener(event);
}

public function removeEventListener(type:String, listener:Function, ...):void
{
    delete this._listeners[type][listener];
}

      

Suppose you really want to implement IEventDispatcher (instead of using another EventDispatcher - you may have reasons for this, one such reason is that the native EventDispatcher generates insane sums of short-lived objects - events, and you can reduce that.) But you cannot replicate event.target or event.currentTurget to your code because you cannot access the object that owns this method, so you can leave that.



Another example:

public class SomeEvent extends Event
{

    private var _target:NotEventDispatcher;

    public function SomeEvent(type:String, someTarget:NotEventDispatcher)
    {
        super(type);
        this._target = someTarget;
    }

    public override function get target():Object
    {
        return this._target;
    }
}

      

This is what I actually saw in the real world, it was used either in Mate or a similar structure to "anonymously" connect all event dispatchers to one static instance of some "Mothership event dispatcher".

I don't necessarily condone this approach, but, technically, nothing stops you from making one of them. What I said in my post above is that in certain situations the promises language you, for example, do:

var dispatcher:IEventDispatcher;
try
{
    dispatcher = IEventDispatcher(event.currentTarget);
    // now you can be sure this object has removeEventListener
    dispatcher.removeEventListener(event.type, arguments.callee);
}
catch (error:Error)
{
    // but what are you going to do here?
}

      

But the most common case is to subscribe to a bubbling event, in which case you don't know if you want to unsubscribe from event.target or event.currentTtarget - because you don't know which one you are listening to.

+5


source


I agree with wvxvw.

Another way to approach your problem is to have a variable to control the "state" of your ENTER_FRAME event:

private var _state:String;

private function init(e:Event):void {
    addEventListener(Event.ENTER_FRAME, loop, false, 0, true);
}

private function loop(e:Event):void {
    switch(_state) {
        case "play":
            // do play stuff
            // when you want to pause
            // goToPause();
        break;
    }
}

// you can call the method below from a button or whatever you want
private function goToPause():void {
    _state = "pause";
    // do some stuff here
    // when you are done, switch "_state" back to "play"
}

      

In this example, you keep listening to ENTER_FRAME, but it only matters when the _state variable goes to "play". You can also remove the event listener in the goToPause method:

private function goToPause():void {
    _state = "pause";
    removeEventListener(Event.ENTER_FRAME, loop);
}

      

However, the good thing about using "_state" to switch things is that you don't have the mess of addEventListeners and removeEventListeners (which can happen depending on how complex your loop is) that you have to watch out for.

+1


source


You cannot use anonymous function call if you want to remove the listener after a while.

public function main():void
{
    //...
    //some method, where you add event listener
    //...

    //adding enterFrame event listener
    this.addEventListener(Event.ENTER_FRAME,enterFrameHandler);

    //...

}

private function enterFrameHandler(e:Event)
{

    if(findObject)  // " == true" is not really necessary here.
    {
        // removing enterFrame listener:
        this.removeEventlistener(Event.ENTER_FRAME,enterFrameHandler);
    }
}

      

0


source


Just for completeness, with the other ways described here, the function being created is an unbound closure, so you can also use this concept to refer to both your function and dispatcher.

var callback:Function;
var dispacher:IEventDispatcher = this;
addEventListener(Event.ENTER_FRAME, callback = function(e:Event){

        if(findObject == true){
            dispacher.removeEventListener(Event.ENTER_FRAME, callback);
        }

});

      

Normal private variable rules apply.

0


source







All Articles