Sunday, June 27, 2010

Flash Player Runtime Errors and How to Fix Them

The following lists common runtime errors found with Flash Player and what you can do to fix them. Also available, Compiler Errors.

TypeError: Error #1009

TypeError: Error #1009: Cannot access a property or method of a null object reference.

This error occurs when you attempt to access a property or call a method (function) from an object variable that has no value (undefined) or has a null value. If the object is null, it has no value itself meaning it cannot contain any properties. The following example would be a situation where the error would occur:

var mySprite:Sprite; // null since not defined trace(mySprite.x); // Error #1009

Because the mySprite variable is null, accessing mySprite.x would be the same as null.x which is not possible, thereby creating the error condition. Note that this behavior is new to ActionScript 3.0. In ActionScript 2.0 and 1.0, doing this would cause a silent failure and return a value of undefined.

Usually when this error occurs, it means an error in your code logic. You're code is assuming an object exists when it does not. That is something you will have to identify and fix. This can sometimes be difficult because of the error's ambiguous text; it does not specify what specific object the error is in reference to. However, if you test a debug version of your project in your IDE, it will tell you.

Debugging in Adobe Flash Professional:

From the File menu, select Debug > Debug Movie.

Debugging in Flash Pro

Debugging in Adobe Flash Builder:

From the File menu, select Run > Debug [ProjectName].

Flash Builder Debugging

When debugging (in either Flash Pro or Flash Builder), a Debug version of your project which will include more information about code execution that can help better identify errors. When the error occurs, code execution will pause and the line of code with the error will be pointed out in the code view. Additionally, the Variables panel can be used to inspect the values of the objects and properties within the current scope.

If there is a circumstance where it is known that an object may or may not exist, then you would first need to check to see if the object being used has a value before attempting to access properties or call methods from it. This can be handled through a simple if condition.

if (mySprite){  trace(mySprite.x); }

Alternatively, you can also encase your logic in a try-catch block, directly handling any error that may occur.

try {  trace(mySprite.x); }catch(err:Error){  // it's OK, we know mySprite may not exist }

Common circumstances where a #1009 may occur:

  • root, stage, or loaderInfo is null. The root, stage, and loaderInfo properties of the DisplayObject class are unique in that their values are dictated by whether or not the DisplayObject is a child of the active display list. If the DisplayObject is not, these properties will each be null. They will not have valid values until the object made a child of the active display list throughaddChild or addChildAt. You can identify when this occurs using the Event.ADDED_TO_STAGE event.
    addEventListener(Event.ADDED_TO_STAGE, stageAndRootAndLoaderInfoAvailableHandler);
  • A variable is declared, but not defined. As is the case with the mySprite examples, the mySprite variable was declared, so it exists, but it was never defined with a valid Sprite value. This can be common when creating new classes where you have correctly declared all of the necessary variable members but may have neglected to define them before they're being accessed.
  • A timeline instance no longer exists. If you navigate to a frame within the timeline of a MovieClip that no longer has a timeline-placed object you're referencing in code, that object variable will be null. You will need to make sure you're on the correct frame or at least check to see if the object variable is still valid when used.

ReferenceError: Error #1056

ReferenceError: Error #1056: Cannot create property [property] on [Type]

This error occurs when you try to create a new variable on an object that does not already have that variable and is not allowed to have new variables created for it dynamically. Only instances of dynamic classes can have arbitrary variables defined for them. These classes include Object, Array, MovieClip, and a few others. Most classes, however, are not dynamic and limited to use only those variables which are part of their class's definition.

var mySprite:* = new Sprite(); // untyped to circumvent compiler errors mySprite.foo = "bar"; // Error #1056

The Sprite class is not dynamic so the variable mySprite above generates an error when an unrecognized variable foo is attempted to be set on it.

If you are in a situation where you need to set a variable in this manner, you have a couple of options. One option is creating a new class that extends the original and contains the property you need to use. For the case of mySprite above, a new class extending Sprite can be created to used in place of Sprite that contains the foo property.

// in CustomSprite.as package {  import flash.display.Sprite;  public class CustomSprite extends Sprite {   public var foo:String;   public function CustomSprite(){    super();   }  } }
var mySprite:CustomSprite = new CustomSprite(); mySprite.foo = "bar"; // OK

If you do not have control over the definition of the object you're working with, usually the best solution is making a hash map. A hash map (or simply map) will allow you to link a custom value with a unique key, or in this case an object, in a location other than within the object itself. Generic objects in ActionScript can map strings to values but for this to work - mapping values to object instances - a Dictionary instance will be needed for the map. Example:

var foo:Dictionary = new Dictionary(true); var mySprite:Sprite = new Sprite(); foo[mySprite] = "bar"; // OK

Here, you can see that instead of setting a property on the mySprite Sprite, mySprite is instead being used as a property on a fooDictionary (map). As long as you have access to both foo and the Sprite instance, you have access to custom values that are directly associated with that Sprite even though they are not defined on it. The nature of the map allows it to be used with any other objects as well, not just the mySprite instance. If at any time you need more custom variables, you would create a new map.

var foo:Dictionary = new Dictionary(true); var boo:Dictionary = new Dictionary(true);  var mySprite:Sprite = new Sprite(); foo[mySprite] = "bar"; // OK boo[mySprite] = "far"; // OK  var myMovieClip:MovieClip = new MovieClip(); foo[myMovieClip] = "none"; // OK boo[myMovieClip] = "away"; // OK

Hash maps are very versatile but they lack type safety and can be difficult or confusing to manage. When possible, it's recommended you use a custom class to solve this issue.

ArgumentError: Error #1063

ArgumentError: Error #1063: Argument count mismatch on [function](). Expected [#], got [#].

This occurs when a function is called in a way that does not satisfy the number of arguments that is expected for the function call. When a function is defined, it's parameters determine what arguments is expected to be passed into that function when the function is called. Unless given a default value, all parameters are required. Additionally, if a function has no parameters but arguments are provided when called (or more arguments than there are parameters are provided) this error will also occur. Examples:

function myAddFunction(a:Number, b:Number):Number {  return a + b; }  myAddFunction(1); // Error #1063 // exactly two arguments are required 
function myRandomFunction():Number {  return Math.floor( 10 * Math.random() ); }  myRandomFunction(1); // Error #1063 // exactly zero arguments are required

When function calls are made, the arguments used must match the parameters defined by the function definition. Note that this behavior is new to ActionScript 3.0. In ActionScript 2.0 and 1.0, doing this would cause a silent failure and the superfluous arguments would be ignored.

If you need to allow a function to be called with a varying number of arguments, you have two options: default parameters and the ...rest parameter. Default parameters specify optional parameters. Arguments may be passed into a function to satisfy these parameter values or they can be omitted at which point the default values will be used. To define default parameters, include an equals sign (=) with a default value next to the parameter in the function definition. All default parameters must be at the end of a parameters list; non-default parameters cannot be listed after a default parameter.

function myAddFunction(a:Number, b:Number = 0):Number {  return a + b; }  myAddFunction(1, 2); // standard use myAddFunction(1); // also OK, b will default to 0 myAddFunction(); // Error #1063, a is still required

The ...rest parameter signifies that any number of arguments can be used in place of where the ...rest is in the parameter list. Any required parameters before ...rest are still required. When using ...rest, any variable name may be used to signify the extra parameters. It must be preceded by 3 dots (.) and must not be followed by any additional parameters. In the function body, the ...rest variable references an array containing any arguments used in place of the ...rest parameter.

function myAddFunction(...values):Number {  var total:Number = 0;  var i:int, n:int = values.length;  for (i=0; i

Common circumstances where a #1009 may occur:

  • Event handlers. If you create a function that is used for an event handler, it must be able to accept single Event argument.
    addEventListener(Event.ENTER_FRAME, enterFrame); function enterFrame():void {  // Error #1063, an event parameter is required! }
    addEventListener(Event.ENTER_FRAME, enterFrame); function enterFrame(event:Event):void {  // Works! }

ArgumentError: Error #2025

ArgumentError: Error #2025: The supplied DisplayObject must be a child of the caller.

This occurs when you try to use a removeChild with a display object that does not exist within the parent object you are trying to remove it from. For example, in the following sample where myParent is a Sprite or some other DisplayObjectContainer instance that (supposedly) contains a child Sprite (or some other DisplayObject) called myChild:

myParent.removeChild(myChild);

this error would occur if the myParent instance (the "caller") did not contain myChild (the "supplied DisplayObject"). This could be because myChild was already removed prior to this call, or myChild exists within some other object. If this is happening when you think it shouldn't, try tracing the value of the child display object's parent to see if it's what you expect.

To be safe, when removing a child display object from its container, you should make sure the object you're removing it from is, in fact, it's parent.

if (myChild.parent == myParent) {  myParent.removeChild(myChild); }

This goes with the assumption that you need to explicitly remove that child from that specific parent. If you just want to remove the child from the display list, you can explicitly reference it's own parent through its own parent property rather than an object reference for the object you suspect might be its parent. In doing so, you should check to see that parent exists. If it's null, it is already off of the display list.

if (myChild.parent) {  myChild.parent.removeChild(myChild); }

This is the standard approach for removing an object from the display list. Verify it's on the display list (parent is not null) then remove the object from it's parent directly.

There is one exception to this rule: event handlers for the Event.REMOVED event when a timeline containing the child display object moves to a frame where the child does not exist. In this case, parent will be non-null but the removeChild will not work because the child display object is actually no longer on the display list. This circumstance would be extremely rare, but for absolute assurance that your code would continue without interference, you can attempt to handle the error in a try-catch block when attempting to remove the child display object with removeChild.


if (myChild.parent) {  try {   myChild.parent.removeChild(myChild);  }catch(err:Error){   // fail silently; child already removed  } }    
source link : http://www.senocular.com/flash/tutorials/runtimeerrors/

No comments: