Thursday, January 6, 2005

removeMovieClip and onUnload conflict

Happy New Year!,
Don't know about you but this year it's felt really hard to get back into the swing of things again after christmas.

Anyway down to business this is a problem that I realize has been around for a while and I couldn't quite get to the bottom of it so I just worked around it but finally I decided to squash it once and for all.

The Problem:
There are a number of places where we might want to delete and recreate a series of masked clips through actionscript basically just like a reset, rebuild the clips same instance name, same initial properties.

When we did this we noted that after creating and then masking them for the second time the setMask call failed and our "mask" was visible on screen.
We looked for reason why the setMask call didn't work but couldn't see what was wrong. Anyway we were looking in the wrong place the issue was not the setMask call it was the removeMovieClip call beforehand.

Now when we watched in the debugger the clips disappeared as they should but we found that we could still find the clips via trace. Admittedly all the properties had gone and any child clips had disappeared but strangely some method worked and we found that getDepth() returned a negative value equal to 32769 + the original depth. Well the docs say that's not a legal depth. Then when we created the new clips reusing the instanceId they were created but the depth was still this illegal large negative value. I guess in that state it was not surprising that setMask wasn't going to work.

We then tried to figure out what caused the depth to change when we simply called removeMovieClip. Well after working our way through the code we eventually saw it was a simple onUnload handler that was the root of all this evil. The handler wasn't doing anything it was just "there", but if it was removed the clips went away nicely if it was set (even to null) then the clips wouldn't get properly removed.

Now the docs say the onUnload handler is called on the frame after the clip is unloaded (never did understand why) so I guess its hanging around so it can invoke the handler but the docs also say removeMovieClip wipes out your handlers and its true onUnload never gets invoked when you call removeMovieClip. However even though its not invoked it still prevents the clip from being removed immediately.

Now given the above explanation we did wonder what would happen if we gave the clips a frame to get themselves sorted out before recreating them again. It did help at leas the depth straightened itself out but we still couldn't get the setMask call to work.

In any event a frames pause was not a workable solution in this case as we need to delete and create in the same call.

So we renamed the onUnload function onDestroy then provided a mechanism for that to be invoked by removeMovieClip.

Its not a big deal but its a small gotcha.

On reflection though I think we really should have an onRemove or on Destroy event for MovieClips that are "removed" so that we can gracefully handle tidying up before a clip is killed whether it is by unloading or removing.



2 comments:

  1. >On reflection though I think we really should >have an onRemove or on Destroy event for >MovieClips that are "removed" so that we can >gracefully handle tidying up before a clip is >killed whether it is by unloading or removing.
    Amen Brother.

    ReplyDelete
  2. I had a similar problem with seemingly random problems that were all related to onUnload, things like components not initializing, etc. It's a shame it's buggy like that.

    ReplyDelete