Suggerimento rapido come eseguire il debug di un errore AS3 n. 1009

Una delle domande più comuni che vedo sui forum e dai colleghi è come eseguire il debug dell'errore 1009, noto anche come "Errore di riferimento agli oggetti Null". O, come lo chiamo, il? Fastidioso Mosquito Error From Hell.? Sorge molto, e sfortunatamente l'errore in sé non contiene molte informazioni sulla fonte dell'errore. In questo suggerimento, daremo un'occhiata ad alcuni passi che puoi seguire per rintracciare questa zanzara e schiacciarla.


introduzione

Questo pezzo è il primo seguito ai più generali bug di riparazione in AS3? tutorial. Se desideri comprendere meglio alcune delle tecniche di questo suggerimento, potresti prima leggerlo per intero.


Passaggio 1: capire l'errore

Peccato che Adobe non (o non possa) fornire ulteriori informazioni sulla radice di questo errore. Prima di tutto, è piuttosto formulata in modo ottusamente (molto simile a tutti i loro errori, ma questo più della maggior parte):

TypeError: Errore # 1009: impossibile accedere a una proprietà oa un metodo di riferimento a un oggetto nullo

Proviamo a metterlo in termini quotidiani. L'errore 1009 significa che hai provato a fare qualcosa con una variabile che presumi abbia un valore, ma in realtà non lo fa. A Flash non piace. Non ti piacerebbe neanche; Immagina di avere un bicchiere che hai immaginato fosse pieno della bevanda gustosa di tua scelta, ma in realtà era vuoto. Prendi il bicchiere, aspettandoti un sorso rinfrescante, ma senti invece il peso deludente di un bicchiere vuoto. Questo è il tuo errore personale 1009.

In ActionScript, se si esegue questa operazione:

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

Flash si romperà duramente (un termine tecnico per? Produrre un errore?) Quando si esegue il codice. La variabile S potrebbe essere stato dichiarato, ma il suo valore è nullo (non impostiamo mai il valore, abbiamo appena dichiarato la variabile), quindi chiamiamo il toUpperCase il metodo su di esso è problematico.

Per essere chiari, perché S è dichiarato come a Stringa, il compilatore non prende alcun problema con il codice: c'è una variabile chiamata S, è un Stringa, e toUpperCase è un metodo valido per chiamare StringaS. L'errore che otteniamo è a run-time errore, il che significa che lo otteniamo solo quando eseguiamo il file SWF. Solo quando viene eseguita la logica, ora vediamo come questo si rivela.


Passaggio 2: consentire il debug

Come con qualsiasi errore di run-time, a volte è abbastanza facile dire cosa sta succedendo senza ulteriori informazioni. Ma altre volte è utile restringere ulteriormente questo aspetto. A questo punto, prova ad attivare? Permettere il debug.? Quando è abilitato, ricevi degli errori che ti danno anche dei numeri di linea. In alternativa, potresti riuscire a "Debugare film"? premendo Comando-Maiusc-Ritorna / Controllo-Maiusc-Invio.

Per fare ciò, consultare l'articolo generale sui suggerimenti per il debug, "Correggere i bug in AS3?

A volte questo è abbastanza. Conoscere la linea specifica potrebbe essere tutte le informazioni necessarie. Altrimenti, scaveremo un po 'più in profondità nel prossimo passo.

Il nostro caro editor, Michael James Williams, ha riassunto il punto di questo passaggio in un limerick, che sono felice di presentarvi ora con il suo gentile permesso:

Errore AS3 one-oh-oh-nine
Non è mai un buon segno.
Non c'è motivo di preoccuparsi,
Premi Ctrl-Maiusc + Invio
E individuerà la causa (beh, la linea).


Passaggio 3: Inizia la traccia

Se hai individuato la linea incriminata ma non sai ancora cosa sta succedendo, scegli la linea. Prendi tutte le variabili in quella linea e tracciarle precedente a l'errore.

Poiché l'errore si verifica quando si accede a una proprietà o si chiama un metodo su una variabile nulla, per coprire le basi si devono tracciare tutte le variabili e le proprietà immediatamente seguite da un punto. Ad esempio, prendi questa riga di codice:

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

Certo, è un pezzo di codice piuttosto inventato che non riesco a immaginare per un uso pratico, ma dovresti identificarlo quattro totale possibile nullo valori a cui si accede con il punto:

  • myArray: stiamo chiamando il Spingere metodo su questa variabile
  • someSprite: stiamo accedendo al palcoscenico proprietà
  • palcoscenico: stiamo accedendo al allineare proprietà
  • allineare: stiamo chiamando il toLowerCase metodo

Quindi il tuo codice di debug potrebbe essere simile a questo:

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

L'ordine è importante; Se someSprite è l'oggetto nullo, ma si prova per someSprite.stage.align prima di provare per someSprite, si finisce con risultati meno definitivi.

Ora, anche il buon senso gioca su questo. Nel mio esempio, se palcoscenico esiste, quindi allineare avrà sicuramente un valore; il Palcoscenico ha sempre un allineare impostazione, anche se è il valore predefinito.

In genere, vedrai qualcosa di simile al seguente:

 myArray: [? roba nell'array? ] someSprite: [object Sprite] someSprite.stage: null Errore # 1009:? 

Quale dovrebbe indurvi in ​​quello il palcoscenico la proprietà è nullo, e ora puoi andare a ripararlo.


Passaggio 4: ricerca di una soluzione

La soluzione più semplice è quella di concludere la frase incriminata in un? If? blocco, e solo eseguire il blocco se la variabile in questione non è nullo. Quindi, supponendo che nel nostro esempio precedente, fosse in effetti palcoscenico quello era nullo, potremmo fare qualcosa del genere:

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

Questo test - se (someSprite.stage) - tornerà vero se c'è un valore (indipendentemente dal valore), e falso se è nullo. In generale questa notazione funziona; puoi sempre usare if (someSprite.stage! = null) se preferisci. Numeros presentare una situazione leggermente diversa, però. Se la Numero ha un valore di 0, quindi tecnicamente ha un valore, ma prova se (someNumberThatEqualsZero) valuterà a falso. Per Numeros puoi usare il isNaN () funzione per determinare se un valore numerico valido è memorizzato in una determinata variabile.

Ad ogni modo, questa tecnica è un modo semplice per eludere l'errore. Se la variabile su cui vogliamo eseguire un'operazione non è impostata, non eseguire l'operazione. Se non ci sono bevande gustose nel nostro bicchiere, non raccogliere il bicchiere. Abbastanza semplice.

Ma questo approccio è possibile solo se la logica è opzionale. Se è necessaria la logica, allora è possibile fornire un valore predefinito alla variabile discutibile prima dell'operazione di errore. Ad esempio, se myArray ha il potenziale per essere nullo, ma è imperativo che non lo sia, possiamo farlo:

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

Questo prima controllerà per vedere se l'array è nullo. Se lo è, inizializza su una matrice vuota (una matrice vuota è un valore valido. Può essere vuota, ma è una matrice, e non nullo) prima di eseguire la linea di codice forzata. Se non lo è nullo, salta direttamente alla linea di codice inventata. In termini reali, se il nostro bicchiere è vuoto, riempilo con una bevanda gustosa prima di prenderlo.

Inoltre, se myArray è una proprietà di istanza della classe in cui è in esecuzione questa riga di codice, è possibile garantire in modo sicuro un valore valido inizializzando le proprietà quando l'oggetto viene inizializzato.

Cosa succede se la logica è richiesta, ma la variabile in questione non è così prontamente sotto il nostro controllo? Ad esempio, cosa succede se la nostra linea di codice inventata è richiesta, ma la variabile discutibile è someSprite.stage? Non possiamo semplicemente impostare il palcoscenico proprietà; che è controllato internamente a DisplayObject ed è di sola lettura per noi comuni mortali. Quindi potresti aver bisogno di essere furbo e leggere il passaggio successivo.


Passaggio 5: Gestire con a nullo palcoscenico

Ci sono probabilmente un numero infinito di scenari in cui una determinata variabile o proprietà potrebbe essere nullo. Ovviamente, non posso coprirli tutti in un Suggerimento rapido. C'è una situazione specifica, tuttavia, che ricorre continuamente.

Diciamo che scrivi un codice simile a questo:

 public class QuickSprite estende Sprite public function QuickSprite () stage.addEventListener (MouseEvent.MOUSE_MOVE, onMove);  funzione privata onMove (e: MouseEvent): void var color: ColorTransform = new ColorTransform (); color.color = stage.mouseX / stage.stageWidth * 0xFFFFFF; this.transform.colorTransform = color; 

Un altro pezzo di codice inventato (che potrebbe indurre crisi epilettiche - considera te stesso avvisato), ma in fondo l'idea è che tu abbia un folletto sottoclasse e lo imposti come classe per una clip sullo stage, utilizzando l'IDE Flash.

Tuttavia, decidi di voler lavorare con questi QuickSprites a livello di programmazione. Quindi provi questo:

 var q: QuickSprite = new QuickSprite (); addChild (qb);

E ottieni l'errore 1009 maledetto. Perché? Perché nel QuickSprite costruttore, si accede al palcoscenico proprietà (ereditata da DisplayObject). Quando l'oggetto viene creato interamente con il codice, non è sul palco nel punto in cui quella linea di codice viene eseguita, ovvero palcoscenico è nullo e ottieni l'errore Il QuickSprite viene aggiunta la riga successiva, ma non è abbastanza presto. Se l'istanza viene creata trascinando un simbolo fuori dalla libreria e sul palco, c'è un po 'di magia al lavoro dietro le quinte che assicura che l'istanza sia sul palco (cioè, il palcoscenico proprietà è impostata) durante il costruttore.

Quindi, ecco cosa si fa: si prova per l'esistenza di un valore per palcoscenico. A seconda del risultato, è possibile eseguire immediatamente il codice di configurazione o impostare un listener di eventi diverso per quando il file QuickSprite viene aggiunto al palco. Qualcosa come questo:

 funzione pubblica QuickSprite () if (stage) init ();  else this.addEventListener (Event.ADDED_TO_STAGE, init);  funzione privata init (e: Event = null) this.removeEventListener (Event.ADDED_TO_STAGE, init); stage.addEventListener (MouseEvent.MOUSE_MOVE, onMove); 

Se spostiamo il palcoscenico allineare a una funzione diversa, e chiamarla solo quando abbiamo uno stage, quindi siamo impostati. Se palcoscenico esiste fin dall'inizio, andare avanti e correre dentro() subito. In caso contrario, useremo dentro() come funzione di listener di eventi per ADDED_TO_STAGE, a quel punto avremo un valore di stage e possiamo eseguire il codice. Ora possiamo usare la classe per la connessione a IDE Sprite o completamente a livello di programmazione.

Funziona bene anche nelle classi di documenti. Quando si esegue un SWF da solo, la classe del documento ha accesso immediato a palcoscenico. Se si carica quel file SWF in un altro SWF, il codice nello stack di inizializzazione della classe del documento viene eseguito prima che il file SWF caricato venga aggiunto al display. Un simile palcoscenico-il trucco di controllo ti consentirà di lavorare con SWF sia come pezzo autonomo che come SWF caricato in un SWF contenente.


Questo è tutto

Grazie per aver letto questo suggerimento! Spero che tu sia illuminato un po 'su come si verifica l'errore 1009 e su come puoi eseguirne il debug. Restate sintonizzati per ulteriori suggerimenti rapidi su altri errori comuni.