I have been creating a code base for a Screen Manager system that I am using for an iOS app I am building in AS3. I wanted to create a dynamic way to reference and instantiate classes that represent each of the Screens in the app so I can reuse this for other applications in the future and to make it a lot less code intensive.
I setup a series of static variables that held string names to represent each of the Screens in the application. Then when I want to create the screen and add it to the stage I use the getDefinitionByName() method and pass the string name of the class.
In theory, this all made sense and should have worked however I ran into this error that I had never seen before: *(note: StartScreen is the name of the class I was wanting to create an instance of)
ReferenceError: Error #1065: Variable StartScreen is not defined.
I have seen a lot of errors in the 7 years I have been working with Flash and AS3 and there have only been a few where I had absolutely no idea what was causing it. This was one of them.
My first thought was “Of course it’s not defined, there is no variable by that name in my program at all!”, followed quickly by “I hate AS3″. So having no idea I turned to the almighty Google for answers.
I found a few blog posts here and there but there really wasn’t a whole lot of help available. I was able to piece together the fix and thought that someone else may need it so here it is.
Basically it breaks down to 2 ways of using the method. I have always used it when there was an item in my Library with a linkage ID I could pass.
When we do it that way it works:
var _dynamicClass:Class = getDefinitionByName("linkage_name") as Class; var _instance = new _dynamicClass();
The other way ( and the way I was doing it in this case ) is to reference a Class file. This is where the strangeness begins.
Lets say that you have a class called StartScreen and for the sake of simplicity it is in the default package of your application. So if we call the code the same way …
var _screen:Class = getDefinitionByName("StartScreen") as Class; var _instance = new _screen();
we should get an instance of the StartScreen class correct? Nope, we get the #1065 error. In order to get this to work we need to simply state the classname before we call it.
StartScreen var _screen:Class = getDefinitionByName("StartScreen") as Class; var _instance = new _screen();
The above code actually works. I have tested it with the only difference being I pass a variable holding the name of the Class instead of the string literal as above.
Here is an even stranger gotcha to be aware of. The #1065 error says that the variable is not defined so logically we may try something like:
var StartScreen var _screen:Class = getDefinitionByName("StartScreen") as Class; var _instance = new _screen();
This will not work – the same error fires.
Another gotcha is when the class you are referencing is in a package. Then you have to access it via it’s package. To reuse my StartScreen example, lets pretend that all my screens are sitting in a screens package. To access the class we need to prepend the class package to the class name – the same as though you were doing an import:
StartScreen var _screen:Class = getDefinitionByName("screens.StartScreen") as Class; var _instance = new _screen();
I don’t really have any idea why this work the way it does and I can’t seem to find any explanations in the documentation but this is the way I got it to work for me. If anyone has any suggestions, explanations or knows a better way – I’d love to know about it.