GhostWire Studios - Flash/Flex UI Components Development And Consulting Services
Quality User Interface Controls For Flash Application DevelopmentAspireUI Components

Aug 18 2009

[AS3] Avoiding NULL Object Reference Error When Loading Module SWF

Published by sunny at 2:58 am under Flash,Flash AS3,Tips

When building modular Flash applications, a common error that may be encountered is that related to accessing a property or method of the stage property when it is still null. If a display object is not yet added to the display list, its stage property returns null.

An ActionScript error has occurred: “Cannot access a property or method of a null object reference.”

Quite a cryptic message, especially if you test the module SWF standalone and nothing seems wrong, but the error is thrown when you load the module SWF into a host SWF.


Background of the Problem
When a module SWF is loaded into a host SWF, the constructor of the top-level class of the module SWF will be called before the instance itself (Sprite or MovieClip) is added to the display list. In other words, the stage property will still be null when the class is being instantiated and therefore, referencing a property or method of the Stage object (via the stage property) in the constructor of the top-level class will result in a “null object reference” error.

The same occurs, of course, if the constructor does not reference a property or method of the stage directly, but calls another member (function or get/set property) that does so.


Example of the Problem
Let’s take for example we want the application to be notified when the Stage is resized and will therefore attach a listener to the Stage. The following will work if the SWF is run standalone, but will throw the “null object reference” error if it is loaded into a host SWF:

package 
{
	import flash.display.Sprite;
	import flash.events.Event;
 
	public class Module extends Sprite 
	{
		public function Module()
		{
			init();
		}
 
		private function init():void
		{
			stage.addEventListener(Event.RESIZE, on_stageResize);
			// stage is null, cannot access method of null object, error is thrown
		}
 
		private function on_stageResize(evt:Event):void
		{
			// ** actual application code begins **
			trace("stageWidth: " + stage.stageWidth + " stageHeight: " + stage.stageHeight);
		}
	}	
}


Fix for the Problem
To avoid such an error, simply wait until the display object has been added to the Stage before referencing its stage property. You can do this by listening to the Event.ADDED_TO_STAGE event:

package 
{
	import flash.display.Sprite;
	import flash.events.Event;
 
	public class Module extends Sprite 
	{
		public function Module()
		{
			addEventListener(Event.ADDED_TO_STAGE, init);
		}
 
		private function init(evt:Event):void
		{
			removeEventListener(Event.ADDED_TO_STAGE, init);
			// remove the event listener, because it is possible for the instance
			// to be removed from its container, and re-added to the display list
			// and invoking the event again but we want to call the init method
			// only once per instance of the class
 
			// ** actual application code begins **
			trace(stage); // stage is no longer null
			stage.addEventListener(Event.RESIZE, on_stageResize);
		}
 
		private function on_stageResize(evt:Event):void
		{
			// ** actual application code begins **
			trace("stageWidth: " + stage.stageWidth + " stageHeight: " + stage.stageHeight);
		}
	}	
}


As mentioned above, even if the constructor itself does not reference a property or method of the stage directly, but calls another member (function or get/set property) that does so, or the member calls another member that does so, and so on (you get the idea)… this “null object reference” error will still occur. The referencing may be deeply nested, and therefore, it is probably best to make it a habit to have your top-level class listen for the Event.ADDED_TO_STAGE event before executing other code:

package 
{
	import flash.display.Sprite;
	import flash.events.Event;
 
	public class Module extends Sprite 
	{
		public function Module()
		{
			if (stage) init();
			else addEventListener(Event.ADDED_TO_STAGE, init);
		}
 
		private function init(e:Event = null):void 
		{
			removeEventListener(Event.ADDED_TO_STAGE, init);
 
			// ** actual application code begins **
			trace(stage); // stage is no longer null
		}
	}	
}


FlashDevelop
If you are using the FlashDevelop IDE, the Main.as class file, written in the way described above, will be created automatically for you when you create a new Project using the “AS3 Project” template. However, when writing module classes and compiling them using the Quick Build command, it will be up to you to remember to write them in the way described above (and it is especially for module SWFs that you need to do this).


Reminder:
A Flash application has only one Stage object – display objects in both the host SWF and in any loaded SWF(s) reference the same Stage. Do not confuse stage with the root property.

pixelstats trackingpixel
Share or Bookmark This Post:
  • StumbleUpon
  • email
  • Digg
  • del.icio.us
  • Facebook
  • Google Bookmarks
  • Live
  • Yahoo! Buzz
  • Netvibes
  • NewsVine
  • Reddit
  • Slashdot
  • Technorati
  • BlinkList
  • Mixx
  • Diigo
  • Faves
  • Suggest to Techmeme via Twitter
  • Twitter

Other Posts You Might Enjoy:

       

4 responses so far

4 Responses to “[AS3] Avoiding NULL Object Reference Error When Loading Module SWF”

  1. Alex Angelicoon 27 Oct 2009 at 8:51 pm

    Dear Sunny, THANK YOU VERY MUCH!!!!
    I didn’t had a clue how to solve this issue, and your solution is so simple and clear!!!

  2. MicLon 30 Nov 2009 at 3:30 pm

    Thanks for this post. Cleared things up for me :)

  3. Murdochon 21 Dec 2009 at 3:24 am

    This is exactly what I was looking for. It was doing my head in. Another fix is putting all code on the 2nd frame of the loaded SWF but this approach is much more elegant and correct. My Flash IDE approach is below (all code on first frame of loaded SWF):

    this.addEventListener(Event.ADDED_TO_STAGE, init, false, 0, true )
    function init(event:Event):void {
    trace(MovieClip(this.parent.parent));
    // calls to main timeline will now work
    }

  4. Rasmuson 18 Mar 2010 at 4:05 pm

    thank you thank you thank you thank you thank you thank you thank you thank you thank you thank you thank you thank you thank you thank you!! This was killing me – I was thinking about a career change!

Comments RSS

Leave a Reply

*
To prove you're a person (not a spam script), type the security word shown in the picture. Click on the picture to hear an audio file of the word.
Click to hear an audio file of the anti-spam word