Consejo rápido Cómo depurar un error AS3 # 1009

Una de las preguntas más comunes que veo en los foros y que recibo de mis colegas es cómo depurar el Error 1009, también conocido como "Error de referencia de objeto nulo". O, como lo llamo, el "Molesto error de mosquito del infierno". Surge mucho y, desafortunadamente, el error en sí no contiene mucha información sobre la fuente del error. En este consejo rápido, veremos algunos pasos que puede seguir para rastrear a este mosquito y aplastarlo bien..


Introducción

Esta pieza es el primer seguimiento de los errores más generales de solución en AS3. tutorial. Si desea comprender mejor algunas de las técnicas de este consejo, puede leerlo primero en su totalidad..


Paso 1: Entender el error

Es una lástima que Adobe no (o no pueda) proporcionar más información sobre la raíz de este error. En primer lugar, está bastante redactado (como todos sus errores, pero más que la mayoría):

TypeError: Error # 1009: No se puede acceder a una propiedad o método de una referencia de objeto nula

Tratemos de poner esto en términos cotidianos. El error 1009 significa que ha intentado hacer algo con una variable que asume que tiene un valor, pero realmente no lo hace. A Flash no le gusta eso. A ti tampoco te gustaría; imagina que tenías un vaso que asumiste que estaba lleno de la sabrosa bebida de tu elección, pero realmente estaba vacío. Agarras el vaso, esperando un refrescante trago, pero en cambio sientes el peso decepcionante de un vaso vacío. Ese es tu propio error personal 1009.

En ActionScript, si haces esto:

 var s: String; trace (s.toUpperCase ());

Cuando se ejecuta el código, Flash se descompone (¿un término técnico para "producir un error?"). La variable s Puede haber sido declarado, pero su valor es nulo (nunca establecimos el valor, solo declaramos la variable), por lo que llamar a toUpperCase El método es problemático.

Que quede claro, porque s se declara como Cuerda, la compilador No toma ningún problema con el código: hay una variable llamada s, es un Cuerda, y toUpperCase es un método válido para llamar Cuerdas. El error que obtenemos es un tiempo de ejecución error, lo que significa que solo lo obtenemos cuando ejecutamos el SWF. Solo cuando se realiza la lógica, ahora podemos ver cómo resulta esto.


Paso 2: Permitir la depuración

Al igual que con cualquier error de tiempo de ejecución, a veces es bastante fácil saber qué está pasando sin ninguna información adicional. Pero otras veces es útil reducir esto aún más. En este punto, intente activar "Permitir depuración". Cuando esto está habilitado, obtienes errores que también te dan números de línea. Alternativamente, puede ser capaz de? Debug Movie? presionando Comando-Shift-Return / Control-Shift-Enter.

Para hacerlo, consulte el artículo de consejos generales de depuración,? Solucionar errores en AS3?

A veces esto es suficiente. Conocer la línea específica puede ser toda la información que necesita. Si no, vamos a profundizar un poco más en el siguiente paso.

Nuestro querido editor, Michael James Williams, resumió el punto de este paso en un paletazo, que me complace presentarle ahora con su amable permiso:

AS3 error one-oh-oh-nine
Nunca es una muy buena señal.
No hay necesidad de preocuparse,
Presiona Ctrl-Shift-Return
Y señalará la causa (bueno, la línea).


Paso 3: Iniciar el rastreo

Si ha localizado la línea ofensiva pero aún no está seguro de lo que está pasando, desmonte la línea. Toma todas las variables en esa línea y síguelas antes de el error.

Debido a que el error se produce al acceder a una propiedad o al llamar a un método en una variable nula, para cubrir sus bases, debe rastrear cualquier variable y propiedad que sea seguida inmediatamente por un punto. Por ejemplo, tome esta línea de código:

 myArray.push (someSprite.stage.align.toLowerCase ());

Es cierto que es un código de código bastante artificial que no puedo imaginar para un uso práctico, pero debes identificar cuatro total posible nulo Valores a los que se accede con el punto:

  • myArray: estamos llamando al empujar método en esta variable
  • algunosSprite: estamos accediendo a la escenario propiedad
  • escenario: estamos accediendo a la alinear propiedad
  • alinear: estamos llamando al toLowerCase método

Entonces tu código de depuración podría verse así:

 trace ("myArray:", myArray); trace ("someSprite:", someSprite); trace ("someSprite.stage:", someSprite.stage); trace ("someSprite.stage.align:", someSprite.stage.align);

El orden es importante; Si algunosSprite es el objeto nulo, pero prueba para someSprite.stage.align antes de probar para algunosSprite, terminas con resultados menos definitivos.

Ahora, el sentido común también juega en esto. En mi ejemplo, si escenario existe, entonces alinear seguramente tendrá un valor; la Escenario siempre tiene un alinear configuración, incluso si es el valor predeterminado.

Normalmente, verás algo como lo siguiente:

 myArray: [? cosas en la matriz? ] someSprite: [objeto Sprite] someSprite.stage: null Error # 1009:? 

¿Qué debería darle una pista en que el escenario la propiedad es nulo, Y ahora puedes ir a arreglarlo..


Paso 4: encontrar una solución

La solución más fácil es cerrar la declaración ofensiva en un? Si? bloque, y solo ejecuta el bloque si la variable en cuestión no es nula. Entonces, asumiendo que en nuestro ejemplo anterior, de hecho fue escenario eso fue nulo, Podríamos hacer algo como esto:

 if (someSprite.stage) myArray.push (someSprite.stage.align.toLowerCase ()); 

Esta prueba - if (someSprite.stage) - volverá cierto si hay un valor (independientemente del valor), y falso si es nulo. En general esta notación funciona; siempre puedes usar if (someSprite.stage! = null) si tu prefieres. NúmeroSin embargo, s presenta una situación ligeramente diferente. Si el Número tiene un valor de 0, Entonces técnicamente tiene un valor, pero probando if (someNumberThatEqualsZero) evaluará a falso. por Números puedes usar el isNaN () función para determinar si un valor numérico válido se almacena en una variable dada.

En cualquier caso, esta técnica es una forma simple de eludir el error. Si la variable en la que queremos realizar una operación no está establecida, entonces no realice la operación. Si no hay una bebida sabrosa en nuestro vaso, no levante el vaso. Suficientemente simple.

Pero ese enfoque solo es factible si la lógica es opcional. Si se requiere la lógica, entonces quizás pueda proporcionar un valor predeterminado a la variable cuestionable antes de la operación de error. Por ejemplo, si myArray tiene el potencial de ser nulo, pero es imperativo que no lo sea, podemos hacer esto:

 if (! myArray) myArray = [];  myArray.push (someSprite.stage.align.toLowerCase ());

Esto primero verificará si la matriz es nulo. Si es así, inicialícelo en una matriz vacía (una matriz vacía es un valor válido. Puede estar vacía, pero es una matriz, y no nulo) antes de ejecutar la línea de código artificial. Si no es nulo, Salta directamente a la línea de código artificial. En términos de la vida real, si nuestro vaso está vacío, llénelo con una bebida sabrosa antes de recogerlo.

Además, si myArray es una propiedad de instancia de la clase en la que se ejecuta esta línea de código; puede garantizar un valor válido de forma bastante segura al inicializar sus propiedades cuando el objeto se inicializa..

¿Qué pasa si se requiere la lógica, pero la variable en cuestión no está tan fácilmente bajo nuestro control? Por ejemplo, ¿qué pasa si nuestra línea de código artificial es requerida, pero la variable cuestionable es someSprite.stage? No podemos simplemente configurar el escenario propiedad; eso es controlado internamente para DisplayObject y es de solo lectura para nosotros simples mortales. Entonces es posible que necesite ser astuto y leer el siguiente paso..


Paso 5: Tratar con un nulo escenario

Probablemente hay un número infinito de escenarios donde una variable o propiedad determinada puede ser nulo. Obviamente, no puedo cubrirlos todos en un Consejo Rápido. Hay una situación específica, sin embargo, que surge una y otra vez.

Digamos que escribes un código que se ve así:

 la clase pública QuickSprite extiende Sprite public function QuickSprite () stage.addEventListener (MouseEvent.MOUSE_MOVE, onMove);  función privada onMove (e: MouseEvent): void var color: ColorTransform = new ColorTransform (); color.color = stage.mouseX / stage.stageWidth * 0xFFFFFF; this.transform.colorTransform = color; 

Otro fragmento de código creado (que podría provocar convulsiones, considérese advertido), pero básicamente la idea es que tenga un Duende subclase y establezca esto como la clase para un clip en el escenario, utilizando el IDE de Flash.

Sin embargo, usted decide que quiere trabajar con estos QuickSprites programmáticamente Así que prueba esto:

 var qs: QuickSprite = new QuickSprite (); addChild (qs);

Y obtienes el maldito error 1009. ¿Por qué? Porque en el QuickSprite constructor, accede a la escenario propiedad (heredada de DisplayObject). Cuando el objeto se crea completamente con código, no se encuentra en el escenario en el punto en que se ejecuta esa línea de código, lo que significa escenario es nulo y te sale el error. los QuickSprite se agrega la siguiente línea, pero no es lo suficientemente pronto. Si la instancia se crea arrastrando un símbolo fuera de la biblioteca y al escenario, entonces hay un poco de magia en funcionamiento detrás de la escena que garantiza que la instancia esté en el escenario (es decir, escenario la propiedad se establece) durante el constructor.

Así que esto es lo que hace: prueba la existencia de un valor para escenario. Dependiendo del resultado, puede ejecutar el código de configuración de inmediato o configurar un detector de eventos diferente para cuando QuickSprite Se añade al escenario. Algo como esto:

 función pública QuickSprite () if (stage) init ();  else this.addEventListener (Event.ADDED_TO_STAGE, init);  función privada init (e: Event = null) this.removeEventListener (Event.ADDED_TO_STAGE, init); stage.addEventListener (MouseEvent.MOUSE_MOVE, onMove); 

Si movemos el escenario línea a una función diferente, y solo llamar a esa función cuando tenemos una etapa, entonces estamos configurados. Si escenario Existe desde el principio, sigue adelante y corre. en eso() inmediatamente. Si no, usaremos en eso() como una función de escucha de eventos para ADDED_TO_STAGE, En ese momento tendremos un valor de etapa y podremos ejecutar el código. Ahora podemos usar la clase para conectarse a IDE Sprite o completamente programáticamente.

Esto funciona bien en clases de documentos, también. Cuando ejecuta un SWF por sí mismo, la clase de documento tiene acceso inmediato a escenario. Sin embargo, si carga ese SWF en otro SWF, el código en la pila de inicialización de la clase de documento se ejecuta antes de que el SWF cargado se agregue a la pantalla. Un similar escenario-El truco de verificación le permitirá trabajar con el SWF como una pieza independiente y como un SWF cargado en un SWF que contiene.


Eso es todo

Gracias por leer este Consejo rápido! Espero que esté un poco iluminado acerca de cómo se produce el Error 1009 y cómo puede depurarlo. Manténgase atento a más consejos rápidos sobre otros errores comunes.