Hack 81 Debug with trace( ) 
The trace( ) action
displays text in the Output panel. Use the trace(
) action to maximum effect as a debugging tool.
Although the debugger
(Window Development Panels Debugger and
Control Debug Movie) is useful for real-time debugging, it
is often easier to use the trace( ) action to
display output in the Output panel. However, trace( )
accepts only one expression for output. To display more
(and more useful data), use string concatenation
(the + operator) to build a more complex
expression for output.
Suppose you want to output information on the following data:
var x:Number = 10;
var y:Number = 20;
var z:Array = [10, 20, 30, 40];
var w:Object = {p1:10, p2:"hello", p3:true};
If x and y contain coordinates,
you might display them in (x, y) format on a single line using:
trace("(" + x + ", " + y + ")");
which displays:
(10, 20)
You can use multiple trace( ) statements or the
"\n" escape sequence to split the
output over more than one line. This:
trace("x is: " + x);
trace("y is: " + y);
and this:
trace("x is: " + x + "\n" + "y is: " + y + "\n");
both display:
x is: 10
y is: 20
When working with arrays, simply tracing the array
(i.e., passing the array to the trace( )
function) will display a list of all the elements in the array.
Assuming the earlier value assigned for z, this
code:
trace(z)
displays:
10,20,30,40
Notice that there are no spaces in the output display for array
contents. To format the output in a more appealing manner, you can
specify a delimiter using the Array.join( )
method:
trace (z.join(", ");
which displays:
10, 20, 30, 40
This code:
trace (z.join("\n");
adds line breaks between items:
10
20
30
40
When working with objects, you need to use a for...in
loop to view the enumerable properties of the object.
Assuming the earlier value assigned for w, this
code:
for (var i in w) {
trace("w." + i + " = " + w [i]);
}
displays:
w.p1 = 10
w.p2 = hello
w.p3 = true
Note that the nonenumerable properties (such as built-in methods and
properties that ActionScript has hidden) can be displayed using the
undocumented ASSetPropFlags( ) function [Hack #82] .
Often your ActionScript doesn't do what you hoped
and you don't know why. The culprit is often an
invalid
instance (you think that a variable holds a valid movie clip or
object instance when in fact it does not), which could be caused by a
programming error or because you mistyped (or forgot) the instance
name in the Properties panel. Unfortunately, the Flash Player fails
silently if it can't perform an operation because
the specified instance is invalid. This can be a difficult problem to
debug because:
It usually occurs when you are creating movie clips dynamically or
when you have a full timeline hierarchy, so the debugger may be too
cluttered to make the problem apparent. Although the instance may be shown in the debugger, it may not have
existed at the start of the frame, or the variable may not have the
scope you expect. To debug this type of problem with the debugger,
you have to set breakpoints and manually step through the code, line
by line, which can be time consuming.
An easier way to see whether your
instance is valid at the point your
code expects it is to use a trace( ) debugging
statement of the form:
for (var i in this) {
if (i.indexOf("myClip", 0) != -1) {
trace(myClip._name + " is on timeline " + this);
}
}
If the instance myClip can be seen on the main
timeline, the line will display "myClip is on
timeline _level0" in the Output panel. Otherwise, it
will display nothing. Notice that the output message is very precise
about what was found and where, the hallmark of a good debug message.
The message "found it!" may not
mean that much six months down the line. Similarly, make sure that
each of your trace( ) statements prints out
different text to distinguish which trace( )
statement was reached. For example, this code displays the type of
the incoming argument. If
incoming is an object, it displays,
"Incoming object in checkObject( ) is of type:
object."
function checkObject(incoming) {
trace("Incoming object in checkObject( ) is of type: "
+ typeof incoming);
}
You can add an identifying string and a
">" to your trace(
) messages in order to make the program's
execution and results easier to understand:
survey.fla > Starting up.
xmlutils > Loaded.
view > Loaded. Let's draw the display.
display > Drawing.
Final Thoughts
Debugging information is usually required at authoring time only, and
you can force Flash to omit all trace(
) actions by checking the Omit Trace
Actions option under File Publish Settings Flash.
This prevents trace( ) statements from being
exported and is the same as globally commenting out all
trace( ) statements in the FLA.
For more complex debugging and to prevent being overwhelmed by the
output from trace( ) statements, you can create
a custom, centralized tracing function. Then, you can manually
comment out the body of the debugging function when you publish the
final site. (For optimal performance, you could comment out each
individual function invocation.)
The following code shows a
simple system to assign a verbosity level to debugging messages.
Debugging messages are queued using the function
cTrace(message,
priority).
If priority is below the
verboseLevel threshold, the message is not
displayed in the Output panel. In the following example, both
messages are seen if you set verboseLevel to 0,
but only the first is seen if you set verboseLevel
to 1.
cTrace = function (message, priority) {
if (priority >= verboseLevel) {
trace(message);
}
};
// Usage:
verboseLevel = 1;
cTrace("Important message", 1); // Displayed
cTrace("Low-priority message", 0); // Not displayed
Another enhancement would be to create message filtering. For
example, if you have a file with many errors, you may want to fix the
most important issues first, followed by the less important ones. The
following code hides all messages that are of a lower priority than
the last most important one. This allows you to hone in on the debug
information that is most likely needed to fix your code. In the
following example, the last message is not seen because a higher
priority error appears to be the one causing the problem.
For example, if the very important message was, "XML
file not loading," the less important message,
"Unexpected characters found in XML
file," would be filtered out until you have the XML
loading in the first place!
cTrace = function (message, priority) {
if (priority >= verboseLevel) {
verboseLevel = priority;
trace(message);
}
};
// Usage:
verboseLevel = 0;
cTrace("XML file not loading", 2);
cTrace("Unexpected characters found in XML file", 1);
Finally, you can also output messages using text fields if you want
to test outside the authoring environment (such as in the browser).
The following code modifies the previous listing to redirect
diagnostics information to a text field instance,
myText, presumed to exist on the Stage (changes
are shown in bold). The easiest way to stop such output is to change
the layer the text field is on into a guide layer.
cTrace = function (message, priority) {
if (priority > verboseLevel) {
verboseLevel = priority;
myText.text += message + "\n";
}
};
|