Jump to content
Search Community

SWFLoader problem with REMOVED_FROM_STAGE

luk test
Moderator Tag

Recommended Posts

Hi,

 

First thank You for great classes and sorry for any mistakes in my english.

 

I have a little problem with newer SWFLoader versions (probably from 1.766).

My external SWF contain this:

(...)

if(stage == null) {
addEventListener(Event.ADDED_TO_STAGE, added, false, 0, true);
}
else {
added();
}


function added(event:Event = null):void
{
removeEventListener(Event.ADDED_TO_STAGE, added);

addEventListener(Event.REMOVED_FROM_STAGE, unloadThis);

(...)
}

(...)

function unloadThis(e:Event):void
{
trace("ok");

(...)
}

 

When I load this SWF, first it dispatch REMOVED_FROM_STAGE event so error occur, then go rest of the code. But when I unload this SWF, it don't dispatch REMOVED_FROM_STAGE event again.

 

In earlier versions of SWFLoader everything works correct: load SWF without errors and when unload, it dispatch REMOVED_FROM_STAGE event.

 

 

Maybe something has change or I do it wrong so please correct me.

Link to comment
Share on other sites

Yes, something did change recently and I think you'll find that it's an improvement. Previously, the Loader that SWFLoader used internally wasn't added to the ContentDisplay initially - it waited for the subloading swf to dispatch its INIT event and then it would take the rawContent (the swf's root) and reparent it into the ContentDisplay. That meant that technically when your sub-swf initted, its "stage" was null (because the Loader wasn't in the display list). Some developers wrote code that referenced the stage which would throw errors because of null references (not a bug in LoaderMax, just swfs that weren't coded to take that scenario into consideration). The newer versions of SWFLoader add the internal Loader to the ContentDisplay initially so that when the swf is loaded, its "stage" isn't null (assuming you defined a container or manually added the ContentDisplay to the display list). Then once the swf inits, SWFLoader reparents it out of the Loader and into the ContentDisplay object (basically unwrapping it from the Loader).

 

In AS3, whenever you reparent any DisplayObject that's in the display list, it will fire its REMOVED_FROM_STAGE and ADDED_TO_STAGE events (that has nothing to do with LoaderMax). That's why your code was seeing the REMOVED_FROM_STAGE - it happened when the swf's root was reparented into the ContentDisplay.

 

I wouldn't really recommend coding your stuff that way because technically it would cause your REMOVE_FROM_STAGE logic to run whenever the swf gets reparented anywhere in the parent swf which greatly limits its flexibility. But that's just my opinion.

 

I just posted an updated version of SWFLoader that adds a new suppressInitReparentEvents special property which is true by default. So just update to the latest version and you should be fine.

 

Let me know if that solves things for you.

Link to comment
Share on other sites

Thank You for answer and solving the problem, now it works.

 

I have another question about that what You wrote.

What is the best way to do something (eg. remove listeners) in external SWF when it's unloading or added?

 

Other way, what can I use instead of this:

if(stage == null) {
  addEventListener(Event.ADDED_TO_STAGE, added, false, 0, true);
}
else {
  added();
}


function added(event:Event = null):void
{
  removeEventListener(Event.ADDED_TO_STAGE, added);

  addEventListener(Event.REMOVED_FROM_STAGE, unloadThis);
}

 

Maybe Event.UNLOAD/COMPLETE are better for this?

 

Thanks for any help.

Link to comment
Share on other sites

Good question. Well, if you want to get notified when the parent SWFLoader is unloaded (either via unload() or dispose(true) or canceled in the process of loading), you can use the new version (just posted a few minutes ago) that has an UNLOAD event that gets dispatched. In your sub-swf, you could recursively inspect each parent up the chain and if/when you find a ContentDisplay object (which has a "loader" property), you can add a listener like this:

 

var curParent:DisplayObjectContainer = this.parent;
while (curParent) { 
   if (curParent.hasOwnProperty("loader") && curParent.hasOwnProperty("rawContent")) {
       Object(curParent).loader.addEventListener("unload", dispose, false, 0, true); 
   }
   curParent = curParent.parent;
}

function dispose(event:Event):void { 
   //do cleanup stuff here like removing event listeners, stopping sounds, closing NetStreams, etc... 
}

 

Notice that I didn't do if (curParent is ContentDisplay) because that would force the ContentDisplay and some of the core LoaderMax classes to get compiled into your child swf which would increase its file size. You certainly are welcome to do that - I just wanted to provide the least kb-intensive solution.

 

Again, this is only applicable in version 1.77 and above. I added notes in the ASDocs including the example code above.

http://www.greensock.com/as/docs/tween/_loadermax.html

Link to comment
Share on other sites

Your solution with unload works without problems.

 

Some problem occur when I want to load external gallery and secound SWF (AS3 but i haven't access to code). Both are loading without errors but nothing shows. Everything is ok when I set suppressInitReparentEvents to false. Like You wrote before my coding wasn't recommended. In earlier SWFLoader version both were working by default so maybe better if suppressInitReparentEvents will be false by default?

Link to comment
Share on other sites

Hmm...I don't quite understand the scenario you mentioned. Can you show me how to reproduce the problem? You said you don't have access to the source code, but can you either create your own that gets the same result or at least show me a swf that I can load to see the problem?

Link to comment
Share on other sites

My every external SWF files load and work without any problems but I also have 2 other SWF files which are not my and after load nothing shows (and no error occur). When I set suppressInitReparentEvents to false they are loading and showing corectly. Probably it's related with ADDED_TO_STAGE. When I have set suppressInitReparentEvents to true (by default) I must add some delay in my scroller class eg.:

(...)
if(stage == null)
  addEventListener(Event.ADDED_TO_STAGE, added, false, 0, true);
else
  added(null);

function added(e:Event):void
{
  removeEventListener(Event.ADDED_TO_STAGE,added);
  TweenLite.delayedCall(.5, added2);
  //code go to added2 function
}
(...)

 

Without delay (and with code in "added" function) SWF with this class works correct, but when I loading it from other SWF, error occur (null object - like to fast access). While suppressInitReparentEvents is set to false everything work without problems. In short - when I use Your solution for unload and suppressInitReparentEvents:false everything in my projct work like before.

 

It's not problem for me of course and I'm glad that You help me a lot. I only wrote what I observed.

Link to comment
Share on other sites

There's an error in that code you posted...

 

added(); //function added(e:Event):void {
   ...
}

 

Notice you have one required Event parameter in the function, but you didn't pass any parameter with your added() call.

 

Is there any chance you could send me a sample file that reproduces the problem? I'd really like to nail this down and find out what's going on. It sounds like there may be some faulty code somewhere.

Link to comment
Share on other sites

  • 1 month later...

i don't get it

do i put this code in the loaded swf or in my main class and should it be called from the loaded swf

var curParent:DisplayObjectContainer = this.parent;
while (curParent) {
   if (curParent.hasOwnProperty("loader") && curParent.hasOwnProperty("rawContent")) {
       Object(curParent).loader.addEventListener("unload", dispose, false, 0, true);
   }
   curParent = curParent.parent;
}

function dispose(event:Event):void {
   //do cleanup stuff here like removing event listeners, stopping sounds, closing NetStreams, etc...
}

 

by the please tell me the way to reach a loaded video's Netstream to tell it to close

been a long day and finaly hope on some input from over here ;-)

video = new VideoLoader(Main.M.debugging + videoFile, {name:"vid",prependURLs:Main.M.debugging , container:this.vidMC, width:600, height:400, scaleMode:"proportionalInside", bgColor:0xFFFFFF, autoPlay:true, volume:0.8, requireWithRoot:this.root, estimatedBytes:17500000});
		video.load();

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...