ActionScript 3
Entendiendo el "Error 1009: No se puede acceder a una propiedad o método de referencia de objeto nulo"
Buscar..
Introducción
null
. Los ejemplos proporcionados exponen varios casos donde surge este error, junto con algunas recomendaciones sobre cómo mitigar el error.
Observaciones
El temido y frecuentemente preguntado "Error 1009: No se puede acceder a una propiedad o método de referencia de objeto nulo" es una señal de que algunos de los datos aparecen nulos, pero se intentó utilizarlos como un objeto poblado. Hay muchos tipos de problemas que pueden causar este comportamiento, y cada uno debe compararse con el código donde surgió el error.
Etapa no está disponible
A veces, los desarrolladores escriben algún código que desea acceder a la stage
o etapa de Flash para agregar oyentes. Puede funcionar por primera vez, luego, de repente, deja de funcionar y produce el error 1009. El código en cuestión puede incluso estar en la línea de tiempo, ya que es la primera iniciativa para agregar código allí, y muchos tutoriales que aún existen usan Capa de código de línea de tiempo para colocar el código.
public class Main extends MovieClip {
public function Main() {
stage.addEventListener(Event.ENTER_FRAME,update); // here
La razón por la que este código no funciona es simple: primero se crea una instancia del objeto de visualización, luego se agrega a la lista de visualización, y mientras está fuera de la lista de visualización, la stage
es nula.
Peor aún si el código de esta manera:
stage.addEventListener(Event.ENTER_FRAME,update); // here
se coloca en la línea de tiempo. Incluso puede funcionar durante algún tiempo, mientras que el objeto Main
se golpea para poner en escena a través de GUI. Luego, su SWF se carga desde otro SWF y, de repente, el código se rompe. Esto sucede porque los cuadros del Main
se construyen de una manera diferente cuando el SWF es cargado directamente por el jugador y cuando la carga se procesa de forma asíncrona. La solución es utilizar el escucha Event.ADDED_TO_STAGE
, colocar todo el código que se ocupa de la etapa, y colocar el oyente en un archivo AS en lugar de la línea de tiempo.
Encasillado inválido
function listener(e:Event):void {
var m:MovieClip=e.target as MovieClip;
m.x++;
}
Si dicho oyente se adjunta a un objeto que no es descendiente de MovieClip
(por ejemplo, un Sprite
), la conversión a error fallará y cualquier operación posterior con su resultado arrojará el error 1009.
Objeto no ilustrado
var a:Object;
trace(a); // null
trace(a.b); // Error 1009
Aquí, se declara una referencia de objeto, pero nunca se le asigna un valor, ya sea con una new
o con una asignación de un valor no nulo. Solicitar sus propiedades o método resulta en un error 1009.
Expresión multi-nivel
x=anObject.aProperty.anotherProperty.getSomething().data;
Aquí, cualquier objeto anterior al punto puede terminar siendo nulo, y el uso de métodos que devuelven objetos complejos solo aumenta la complicación para depurar el error nulo. En el peor de los casos, si el método es propenso a fallas extrañas, por ejemplo, recuperar datos a través de la red.
Resultado de la función sin procesar
s=this.getChildByName("garbage");
if (s.parent==this) {...}
getChildByName()
es una de las muchas funciones que pueden devolver nulo si se produce un error al procesar su entrada. Por lo tanto, si está recibiendo un objeto de cualquier función que posiblemente pueda devolver nulo, primero verifique si hay nulo. Aquí, una propiedad se consulta instantáneamente sin verificar primero si s
es nulo, esto generará el error 1009.
Oyente del evento olvidado
addEventListener(Event.ENTER_FRAME,moveChild);
function moveChild(e:Event):void {
childMC.x++;
if (childMC.x>1000) {
gotoAndStop(2);
}
}
Este ejemplo moverá el childMC
(agregado a Main
en el tiempo de diseño) pero lanzará instantáneamente un 1009 tan pronto como se gotoAndStop()
, si ese childMC
no existe en el cuadro 2. La razón principal de esto es que siempre que pasa una cabeza de reproducción un cuadro clave (un cuadro que no hereda el conjunto de objetos del cuadro anterior), ya sea mediante gotoAndStop()
, gotoAndPlay()
con el cuadro de destino separado del cuadro actual por un cuadro clave, o por la reproducción normal si el SWF es un En la animación, los contenidos del marco actual se destruyen y los nuevos contenidos se crean utilizando los datos almacenados desde la GUI. Por lo tanto, si el nuevo marco no tiene un elemento secundario denominado childMC
, la solicitud de propiedad devolverá un valor nulo y se lanzará 1009.
El mismo principio se aplica si agrega dos escuchas de eventos, pero elimina solo una, o agrega una escucha a un objeto, pero intente eliminar de otro. La llamada removeEventListener
no le avisará si el objeto no tiene un detector de eventos respectivo adjunto, así que lea el código que agrega y elimina los escuchas de eventos con cuidado.
También setInterval()
cuenta: al usar objetos del Timer
, al llamar a setInterval()
y a setTimeout()
también se crean escuchas de eventos, y estos también deben borrarse correctamente.
Referencia no válida a un objeto basado en marco
A veces, se llama a gotoAndStop()
en medio del código que hace referencia a algunas propiedades basadas en marcos. Pero, justo después de cambiar el marco, todos los enlaces a las propiedades que existían en el marco actual se invalidan, por lo que cualquier procesamiento que los involucre debe terminarse de inmediato.
Hay dos escenarios generales de tal procesamiento: Primero, un bucle no termina después de la llamada gotoAndStop()
, como aquí:
for each (bullet in bullets) {
if (player.hitTestObject(bullet)) gotoAndStop("gameOver");
}
Aquí, un error 1009 significa que el MC del player
fue destruido al procesar la llamada gotoAndStop()
, pero el bucle continúa, y refiere el enlace ahora nulo para obtener hitTestObject()
. Si la condición diría if (bullet.hitTestObject(player))
lugar, el error sería # 2007 "El parámetro hitTestObject no debe ser nulo". La solución es colocar una declaración de return
justo después de llamar a gotoAndStop()
.
El segundo caso son múltiples escuchas de eventos en el mismo evento. Me gusta esto:
stage.addEventListener(Event.ENTER_FRAME,func1);
stage.addEventListener(Event.ENTER_FRAME,func2);
function func1(e:Event):void {
if (condition()) {
gotoAndStop(2);
}
}
Aquí, si la condition()
es verdadera, el primer oyente ejecutará gotoAndStop()
, pero el segundo escuchador aún se ejecutará, y si esa persona hace referencia a los objetos en el marco, se lanzará un error 1009. La solución es evitar múltiples escuchas en un solo evento, en un solo objeto, es mejor tener un oyente que maneje todas las situaciones en ese evento y pueda terminar adecuadamente si se necesita un cambio de marco.