Hurtig Tips Slik Debugger du en AS3 Feil # 1009

Et av de vanligste spørsmålene jeg ser på fora og få fra kollegaer, er hvordan du feilsøker Feil 1009, også kjent som "Null Object Reference Error." Eller, som jeg kaller det, den? Irriterende Myggfeilen fra helvete.? Det avleder mye, og dessverre inneholder feilen ikke mye informasjon om kilden til feilen. I dette raske tipset tar vi en titt på noen skritt du kan ta for å spore opp denne mygggen og squash den godt.


Introduksjon

Dette stykket er den første oppfølgeren til den mer generelle? Fixing Bugs i AS3? opplæringen. Hvis du ønsker å bedre forstå noen av teknikkene i dette tipset, kan du ønske å lese det i sin helhet først.


Trinn 1: Forstå feilen

Det er synd at Adobe ikke (eller ikke) kan gi mer informasjon om roten til denne feilen. Først og fremst er det ganske tøft formulert (som alle sine feil, men dette er mer enn de fleste):

TypeError: Feil # 1009: Kan ikke få tilgang til en egenskap eller metode for null-objektreferanse

La oss prøve å sette dette i hverdagen. Feil 1009 betyr at du har forsøkt å gjøre noe med en variabel som du antar, har en verdi, men egentlig ikke. Flash liker ikke det. Du vil ikke like det heller; forestill deg at du hadde et glass som du antok var fullt av den velsmakende drikkevaren du ønsket, men det var virkelig tomt. Du tar glasset og forventer en forfriskende snu, men i stedet føler du den skuffende vekten av et tomt glass. Det er din egen personlige feil 1009.

I ActionScript, hvis du gjør dette:

 var s: streng; spor (s.toUpperCase ());

Flash vil bum hardt (et teknisk begrep for? Produsere en feil?) Når du kjører koden. Variabelen s kan ha blitt erklært, men verdien er null (vi har aldri satt verdien, nettopp erklært variabelen), så kaller toUpperCase Metoden på den er plagsom.

Å være klar, fordi s er erklært som en string, de kompilatoren tar ingen problem med koden: det heter en variabel s, det er en string, og toUpperCase er en gyldig metode for å ringe på strings. Feilen vi får er en run-time feil, noe som betyr at vi bare får det når vi kjører SWF. Først når logikken utføres, får vi nå se hvordan dette viser seg.


Trinn 2: Tillat feilsøking

Som med enhver run-time-feil, noen ganger er det ganske enkelt å fortelle hva som skjer uten ekstra informasjon. Men andre ganger er det nyttig å begrense dette videre. På dette tidspunktet kan du prøve å slå på? Tillat feilsøking.? Når dette er aktivert, får du feil som også gir deg linjenumre. Alternativt kan du kanskje? Debug Movie? ved å trykke på Command-Shift-Return / Control-Shift-Enter.

For å gjøre det, se den generelle debugging tips artikkelen,? Feste feil i AS3?

Noen ganger er dette nok. Å vite den spesifikke linjen kan være all den informasjonen du trenger. Hvis ikke, graver vi litt dypere i neste trinn.

Vår kjære redaktør, Michael James Williams, innkapslet poenget med dette trinnet i en limerick, som jeg gjerne presenterer for deg nå med sin hyggelige tillatelse:

AS3 feil en-oh-oh-ni
Er aldri et veldig godt tegn.
Ingen bekymring,
Trykk Ctrl-Shift-Return
Og det vil finne årsaken (vel, linjen).


Trinn 3: Startsporing

Hvis du har funnet den ulovlige linjen, men fortsatt er usikker på hva som skjer, plukk fra linjen. Ta hver variabel i den linjen og spor dem ut i forkant av feilen.

Fordi feilen kommer når du åpner en egenskap eller kaller en metode på null-variabel, bør du spore noen variabler og egenskaper som umiddelbart etterfølges av en prikk for å dekke basisene dine. Ta for eksempel denne linjen med kode:

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

Admittedly, det er en ganske konstruert kode som jeg ikke kan forestille meg en praktisk bruk for, men du burde identifisere fire totalt mulig null verdier som nås med prikken:

  • myArray: vi ringer til trykk metode på denne variabelen
  • someSprite: Vi har tilgang til scene eiendom
  • scene: Vi har tilgang til rette inn eiendom
  • rette inn: vi ringer til toLowerCase metode

Så feilsøkingskoden din kan se slik ut:

 spor ("myArray:", myArray); spor ("noenSprite:", noenSprite); spor ("noenSprite.stage:", someSprite.stage); spor ("someSprite.stage.align:", someSprite.stage.align);

Bestillingen er viktig; hvis someSprite er null objektet, men du tester for someSprite.stage.align før testing for someSprite, du ender med mindre endelige resultater.

Nå spiller også sunn fornuft også inn i dette. I mitt eksempel, hvis scene eksisterer da rette inn vil helt sikkert ha en verdi; de Scene har alltid en rette inn innstilling, selv om det er standardverdien.

Vanligvis ser du noe som følger:

 myArray: [? ting i matrisen? ] someSprite: [object Sprite] someSprite.stage: null Feil # 1009:? 

Hvilket burde clue deg i at scene eiendommen er null, og nå kan du gå om å fikse det.


Trinn 4: Finne en løsning

Den enkleste løsningen er å pakke opp den motsatte setningen i en? Hvis? blokkere, og bare kjør blokken hvis den aktuelle variabelen ikke er null. Så, forutsatt at det i vårt tidligere eksempel var det faktisk scene det var null, vi kunne gjøre noe slikt:

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

Denne testen - hvis (noenSprite.stage) - vil returnere ekte hvis det er en verdi (uavhengig av verdien), og falsk hvis det er null. Generelt fungerer denne notasjonen; du kan alltid bruke hvis (noenSprite.stage! = null) hvis du foretrekker. Nummers presenterer en litt annen situasjon, skjønt. Hvis Nummer har en verdi på 0, så teknisk har det en verdi, men testing hvis (noenNumberThatEqualsZero) vil evaluere til falsk. Til Nummers du kan bruke isNaN () funksjon for å bestemme om en gyldig numerisk verdi er lagret i en gitt variabel.

I alle fall er denne teknikken en enkel måte å skjule feilen på. Hvis variabelen vi vil utføre en operasjon på, ikke er angitt, må du ikke gjøre operasjonen. Hvis det ikke er velsmakende drikke i glasset, må du ikke plukke opp glasset. Enkel nok.

Men denne tilnærmingen er bare mulig hvis logikken er valgfri. Hvis logikken er nødvendig, kan du kanskje gi en standardverdi til den tvilsomme variabelen før feiloperasjonen. For eksempel, hvis myArray har potensial til å være null, men det er viktig at det ikke er det, vi kan gjøre dette:

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

Dette kontrollerer først for å se om arrayet er null. Hvis det er, initialiser det til en tom rekkefølge (et tomt array er en gyldig verdi. Det kan være tomt, men det er en matrise, og ikke null) før du kjører den utprøvde koden. Hvis det ikke er det null, hoppe rett til den utprøvde koden. I virkeligheten, hvis glasset vårt er tomt, fyll det med en velsmakende drikke før du tar den opp.

I tillegg, hvis myArray er en forekomst av klassen der denne linjen med kode kjører, kan du ganske sikkert sikre en gyldig verdi ved å initialisere egenskapene når objektet initialiserer.

Hva om logikken er nødvendig, men den aktuelle variabelen er ikke så lett under vår kontroll? For eksempel, hva om vår konstruerte kodekode er nødvendig, men den tvilsomme variabelen er someSprite.stage? Vi kan ikke bare sette scene eiendom; det styres internt til Displayobject og er skrivebeskyttet for oss bare dødelige. Da må du kanskje bli slank og lese neste trinn.


Trinn 5: Håndtere en null scene

Det er sannsynligvis et uendelig antall scenarier hvor en gitt variabel eller egenskap kan være null. Tydeligvis kan jeg ikke dekke dem alle i en rask tips. Det er en spesiell situasjon, men det kaster opp igjen og igjen.

La oss si at du skriver noen kode som ser slik ut:

 offentlig klasse QuickSprite utvider Sprite offentlig funksjon QuickSprite () stage.addEventListener (MouseEvent.MOUSE_MOVE, onMove);  privat funksjon onMove (e: MouseEvent): void var farge: ColorTransform = new ColorTransform (); color.color = stage.mouseX / stage.stageWidth * 0xFFFFFF; this.transform.colorTransform = color; 

En annen utprøvd bit av kode (som kan forårsake anfall - vurdere deg selv advart), men i utgangspunktet er ideen at du har en Sprite underklasse og du setter dette som klassen for et klipp på scenen, ved hjelp av Flash IDE.

Men du bestemmer deg for at du vil jobbe med disse QuickSprites programmatisk. Så du prøver dette:

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

Og du får den forbannede feilen 1009. Hvorfor? Fordi i QuickSprite Konstruktør, du får tilgang til scene eiendom (arvet fra Displayobject). Når objektet er opprettet helt med kode, er det ikke på scenen på det punktet at den aktuelle koden løper, noe som betyr scene er null og du får feilen. De QuickSprite blir lagt til neste linje, men det er ikke så snart som mulig. Hvis forekomsten er opprettet ved å dra et symbol ut av biblioteket og på scenen, så er det litt magi på jobb bak kulissene som sikrer at forekomsten er på scenen (det vil si at scene eiendommen er satt) under konstruktøren.

Så her er hva du gjør: du tester for eksistensen av en verdi for scene. Avhengig av resultatet kan du enten kjøre oppsettkoden med en gang, eller sette opp en annen hendelselytter for når QuickSprite blir lagt til scenen. Noe sånt som dette:

 offentlig funksjon QuickSprite () hvis (stadium) init ();  annet this.addEventListener (Event.ADDED_TO_STAGE, init);  privatfunksjon init (e: Event = null) this.removeEventListener (Event.ADDED_TO_STAGE, init); stage.addEventListener (MouseEvent.MOUSE_MOVE, onMove); 

Hvis vi flytter scene linje til en annen funksjon, og bare ring den funksjonen når vi har et stadium, så er vi satt. Hvis scene eksisterer fra starten, gå videre og løp i det() med en gang. Hvis ikke, bruker vi i det() som en hendelseslytterfunksjon for ADDED_TO_STAGE, på hvilket tidspunkt vil vi ha en sceneværdi og kan kjøre koden. Nå kan vi bruke klassen for enten å koble til IDE Sprite eller helt programmatisk.

Dette fungerer også bra i dokumentklasser. Når du kjører en SWF av seg selv, har dokumentklassen umiddelbar tilgang til scene. Hvis du laster den SWF-en til en annen SWF, blir koden i dokumentklassens initialiseringsstabel utført før den lastede SWF er lagt til i displayet. En lik scene-kontrolltrick vil tillate deg å jobbe med SWF som både et frittstående stykke og som en SWF lastet inn i en inneholdende SWF.


Det er alt

Takk for at du leser denne raske tipsen! Jeg håper du er opplyst litt om hvordan Feil 1009 oppstår, og hvordan du kan feilsøke det. Hold deg oppdatert for mer raske tips om andre vanlige feil.