AS3 Loader Class best practice - actionscript-3

Recently in a project I configured a custom Loader class as follows
First I define my Loader as a private variabel
private var _myLdr:Loader
//Then in the constructor
_myLdr = new Loader();
_myLdr.contentLoaderInfo.addEventListener( Event.COMPLETE, doneImgLoad );
_myLdr.contentLoaderInfo.addEventListener( ProgressEvent.PROGRESS, loadProgress );
_myLdr.contentLoaderInfo.addEventListener( IOErrorEvent.IO_ERROR, ioError );
And then finally when I need to load a new asset I call my Loader instance via a public method
_myLdr.load(new URLRequest ('myswftoLoad.swf') );
So far so good....UNLESS you happen to view your page using the debug version of FlashPlayer 9.024 in which case you get
ArgumentError: Error #2025: The supplied DisplayObject must be a child of the caller.
at flash.display::Loader/_load()
WTF???!!
So to correct I need to instantiate a new loader EVERY time I load a new asset.
Can someone tell me which method would be considered a 'best practice'?

A Loader instance can have utmost one child at a time. Call _myLdr.unload(); before issuing subsequent load() requests with same Loader instance.
That being said, I would rather create a new Loader instance for each loads (and make sure that previous instances are properly unloaded when they are no longer needed).

Related

AS3: How to instantiate the generic 'Document Class' (MainTimeline?) of a loaded SWF?

I have "Question.swf", which was created from "Question.fla". Note that Question.fla has no Document Class associated with it. (Note that this is legacy content, and there are over 14,000 variants of "Question.swf"; changing all these is not a viable option.)
Now I have my main Flash application, which loads in Question.swf at runtime. I know that Question.swf has a "Document Class" automatically created which represents the entire "stage" of the SWF (and that it's named "MainTimeline"). I want this application to be able to instantiate multiple instances of that Question.swf Document class... how can I?
I've been working with Flash/AS3 since 2006 (I'm very familiar with loading/using external content, the ApplicationDomain, etc.), but I find that I have no idea how to do this!
Things I've tried which haven't worked include querying the relevant ApplicationDomain with hasDefinition( "Question_fla.MainTimeline" ) - this returns false - as well as running getQualifiedClassName() on my loader.content object - this just returns MovieClip.
I'm not sure how to duplicate the main content of the Loader. However, a reasonable workaround might be to load the SWF bytes once and create multiple Loaders from those bytes:
Load your SWF bytes with a URLLoader:
var urlloader : URLLoader = new URLLoader();
urlloader.load(new URLRequest("your url here"));
Once it is loaded, use the bytes to instantiate new display objects:
var loader : Loader = new Loader();
loader.loadBytes(urlloader.bytes);
Use your loaded loader's loader.content display object on the display list (or the loader itself).

AS3: Cannot access a property or method of a null object reference at $iinit while loading external swf

I have two swfs, that works perfect separately, but when i try to load one to other, it shows me "Cannot access a property or method of a null object reference at Creator$iinit".
First SWF is login screen, second is register screen. I load them in this way:
var requestA:URLRequest = new URLRequest("Creator.swf");
var loader:Loader = new Loader();
loader.load(requestA);
addChild(loader);
I have no idea whats wrong. Please, help.
Most likely you're trying to access something that is not available immediately on load and init - you'll need to add some code in the Creator.swf like:
// Somewhere in the first lines of code
addEventListener(Event.ADDED_TO_STAGE, this.ready);
function ready(e:Event) {
removeEventListener(Event.ADDED_TO_STAGE, this.ready);
// ** Do other initialization stuff here
}
What's happening is that you're trying to access the stage or objects before things are ready to accept them.

Difference between getDefinition and getDefinitionByName in AS3

Can somebody explain what is the difference between getDefinitionByName and getDefinition inA AS3?
When I load an external SWF I can't use getDefinitionByName because I get an Error #1065.
But using externalSWF_ContentLoaderInfo.applicationDomain.getDefinition works OK.
So, why getDefinitionByName doesn't find the className?
I mean, if the definition is inside the applicationDomain of the loaded SWF, why is not in the main SWF too? (I'm using Flex).
Offtopic: I can't create new tags so I can't add the tags getDefinition and getDefinitionByName :(
getDefinition is a method of an ApplicationDomain which returns a definition of a class, namespace or function.
getDefinitionByName is a package-level function from flash.utils which returns a Class object that you can use to instantiate new Objects. The definition must already be loaded somewhere in your ApplicationDomain.
The reason you can't make getDefinitionByName with an external SWF is that it is loaded into a separate ApplicationDomain. Your second example works because you are targeting the correct ApplicationDomain. To make your first example work you must load the external SWF into your current ApplicationDomain like this:
var request:URLRequest = new URLRequest("externalSWF.swf");
var context:LoaderContext = new LoaderContext();
context.applicationDomain = ApplicationDomain.currentDomain;
var loader:Loader = new Loader();
loader.load(request,context);
This works because it passes the current ApplicationDomain as a property of the loader context.

Class in loaded SWF cannot use base class in loading SWF

I have two SWF files which I shall call container and slave. The slave file contains a movieclip that extends from a class I shall call base. base extends MovieClip and is compiled into an SWC. slave includes this SWC as a runtime library, while container includes it as merged (and does reference it so it should be compiled into the container SWF).
The container loads the slave like so:
bgURLRequest = new URLRequest(slaveUrl);
var context:LoaderContext = new LoaderContext(false, new ApplicationDomain( null ), SecurityDomain.currentDomain);
bgLoader.load(bgURLRequest, context);
When this loading happens, I get the error that class base was not found. I suspect this has something to do with the presence of the ApplicationDomain in there. I'm not sure what it does exactly, since I didn't write this loading code myself (but I do know that it's there for a reason so it can't be simply removed).
How to fix?
This is the solution
new LoaderContext(false, new ApplicationDomain( ApplicationDomain.currentDomain ), SecurityDomain.currentDomain);
Use ApplicationDomain.currentDomain and track the available classes with the super getDefinitionNames available at: http://etcs.ru/pre/getDefinitionNamesSource/
At least you'll know whats available in the loaded swf.

Flash crash (ends up in a restart loop) when loading an external swf

Im working with FlashDevelop and have two main projects, all pure AS3 projects.
When trying to load my second project from my main project I get all kinds of errors.
The Main class of the main project extends Sprite and the Main class in the "to-be-imported" project extends MovieClip. Looking at the loading of the swf in the debug window in FD it all seems fine:
[SWF] 'pathToSwf'\secondProject.swf - 410 626 bytes after decompression.
If i try to assign the loaded swf to a newly created MovieClip I get a coercion failiure:
swfContent = loader.content; // =>
Type Coercion failed: cannot convert Main#46c0201 to flash.display.MovieClip.
So, typecasting the loaded content like so:
swfContent = loader.content as MovieClip;
removes that error but then I fall into the next pit as I try to call addChild:
Error #2007: Parameter child must be non-null.
Trying to get around the issue I tried to add the loader directly into the container where I want to show the external swf. This is when the real interesting problems begin:
targetContainer.addChild(loader);
My main application now hang, restarting in a never ending loop. I have no idea why..
So my issue is really. How can my external swf be loaded but then again be null.
It works perfectly fine when I run the external swf by itself...
Use getQualifiedClassName and getQualifiedSuperclassName functions (and even describeType if you must) on loader.content to get its exact type information.
loader.content as MovieClip returns null because loader.content is not a MovieClip - casting with as keyword silently returns null when it fails. Is there any chance that the loaded content is an AS2 movie clip instead of AS3 movie clip? In that case getQualifiedClassName will return "AVM1Movie".
The latter issues is weird, but first try changing the type of swfContent to Sprite. A main class does not always extend MovieClip, and judging from the error message it indeed doesn't in this case.
Your swfContent will be null, if it cannot be casted to MovieClip. That is how the as operator is supposed to work when type coercion fails.
Modify your assignment operation like this:
var swfContent :MovieClip = MovieClip(loader.content);
You might want to encompass the assignment in a try...catch block, as an error will be thrown in case of failure, instead of swfContent being set null, as with as.
So the problem was that the main class of my loaded swf had the same name as the swf I was loading from. This led to that when flash tries to execute the loaded swf it actually calls the parent MAIN class which results in the looping behaviour.
To avoid this DHuntrods suggested to change the application domain which solved the issue.
loader = new Loader();
var AD:ApplicationDomain = new ApplicationDomain( null );
var context:LoaderContext = new LoaderContext( false, AD );
loader.load(new URLRequest(path), context);