Una dintre cele mai frecvente întrebări pe care le văd pe forumuri și primesc de la colegi este modul de depanare a erorii 1009, cunoscută și sub numele de "Null Object Reference Error". Sau, așa cum o numesc, "Eroarea enervantă a țânțarilor din iad"? Creste foarte mult si, din pacate, eroarea in sine nu contine prea multe informatii despre sursa erorii. În acest sfat rapid, vom arunca o privire la pașii pe care îi puteți lua pentru a urmări acest țânțar și pentru a-l răsturna.
Această piesă este prima de urmărire la cele mai generale? Fixarea bug-uri în AS3? tutorial. Dacă doriți să înțelegeți mai bine unele dintre tehnicile din acest sfat, vă recomandăm să citiți mai întâi acest lucru.
Este prea rău că Adobe nu (sau nu poate) să furnizeze mai multe informații despre rădăcina acestei erori. Mai întâi de toate, este destul de greu formulat (la fel ca toate erorile lor, dar cu atât mai mult decât majoritatea):
TypeError: Eroare # 1009: Nu se poate accesa o proprietate sau o metodă de referință de obiect nul
Să încercăm să punem acest lucru în termeni zilnici. Eroare 1009 înseamnă că ați încercat să faceți ceva cu o variabilă pe care o presupuneți că are o valoare, dar într-adevăr nu. Flash nu-mi place asta. Nici nu v-ar plăcea; imaginați-vă că ați avut un pahar pe care l-ați presupus că era plin de băutura gustoasă la alegere, dar într-adevăr a fost goală. Luați geamul, așteptând o băutură răcoritoare, dar în schimb simțiți greutatea dezamăgitoare a unui pahar gol. Aceasta este propria ta eroare 1009.
În ActionScript, dacă faceți acest lucru:
var s: String; trace (s.toUpperCase ());
Flash-ul va fi greu (un termen tehnic pentru "produce o eroare?") Când executați codul. Variabila s
poate fi declarată, dar valoarea ei este nul
(nu am stabilit niciodată valoarea, tocmai a declarat variabila), așa că sună toUpperCase
metoda de pe ea este supărător.
Pentru a fi clar, pentru că s
este declarată ca a Şir
, compilator nu are nici o problemă cu codul: există o variabilă numită s
, e o Şir
, și toUpperCase
este o metodă validă de apelat Şir
s. Eroarea pe care o primim este a run-time eroare, ceea ce înseamnă că vom obține doar atunci când vom rula SWF. Numai atunci când se efectuează logica, ajungem acum să vedem cum se dovedește acest lucru.
Ca și în cazul oricărei erori de execuție, uneori este destul de ușor să afli ce se întâmplă fără informații suplimentare. Dar de altădată este util să restrângem acest lucru în continuare. În acest moment, încercați să activați "Permiteți depanarea". Când acest lucru este activat, primiți erori care vă oferă, de asemenea, numere de linie. În mod alternativ, este posibil să puteți debuga filmul? apăsând comanda-Shift-Return / Control-Shift-Enter.
Pentru a face acest lucru, consultați articolul general despre sfaturile de depanare, Fixing Bugs în AS3?
Uneori, acest lucru este de ajuns. Cunoscând linia specifică ar putea fi toate informațiile de care aveți nevoie. Dacă nu, vom săpa puțin mai mult în pasul următor.
Dragul nostru redactor, Michael James Williams, a încapsulat punctul acestui pas într-un limerick, pe care mă bucur să vă prezint acum cu bunăvoința sa:
AS3 eroare one-oh-oh-nine
Nu este niciodată un semn foarte bun.
Nu este nevoie de îngrijorare,
Apăsați Ctrl-Shift-Return
Și va indica cauza (bine, linia).
Dacă ați găsit linia infracțională, dar încă nu sunteți sigur ce se întâmplă, alegeți linia. Luați toate variabilele în acea linie și le urmăriți inainte de eroarea.
Deoarece eroarea apare atunci când accesați o proprietate sau apelați o metodă pe o variabilă nulă, pentru a vă acoperi bazele, ar trebui să urmăriți orice variabile și proprietăți care sunt imediat urmate de un punct. De exemplu, luați această linie de cod:
myArray.push (someSprite.stage.align.toLowerCase ());
Desigur, este o bucată de cod destul de controversată, pentru care nu-mi pot imagina o utilizare practică, dar ar trebui să identificați patru total posibil nul
valori care sunt accesate cu punctul:
myArray
: sunăm Apăsați
pe această variabilăsomeSprite
: accesăm etapă
proprietateetapă
: accesăm alinia
proprietatealinia
: sunăm toLowerCase
metodăDeci, codul dvs. de depanare poate arăta astfel:
urmări ("myArray:", myArray); urmări ("someSprite:", someSprite); urmări ("someSprite.stage:", someSprite.stage); urmări ("someSprite.stage.align:", someSprite.stage.align);
Ordinul este important; dacă someSprite
este obiectul nul, dar încercați pentru someSprite.stage.align
înainte de a testa pentru someSprite
, ajungeți la rezultate mai puțin definitive.
Acum, bunul simț, de asemenea, joacă în acest lucru. În exemplul meu, dacă etapă
există, atunci alinia
va avea cu siguranță o valoare; Etapă
are întotdeauna un alinia
setare, chiar dacă este valoarea implicită.
De obicei, veți vedea ceva asemănător:
MyArray: [? chestii în matrice? ] someSprite: [obiect Sprite] someSprite.stage: null Eroare # 1009:?
Ceea ce ar trebui să vă dau seama de faptul că etapă
proprietatea este nul
, și acum poți să o rezolvi.
Cea mai ușoară soluție este de a încheia declarația ofensatoare într-un? If? bloc și executați blocul numai dacă variabila în cauză nu este nulă. Deci, presupunând că în exemplul nostru precedent, a fost de fapt etapă
asta a fost nul
, am putea face ceva de genul acesta:
dacă (someSprite.stage) myArray.push (someSprite.stage.align.toLowerCase ());
Acest test - dacă (someSprite.stage)
- va reveni Adevărat
dacă există o valoare (indiferent de valoare) și fals
daca este nul
. În general, această notație funcționează; puteți folosi întotdeauna dacă (someSprite.stage! = null)
daca preferi. Număr
dar prezintă o situație puțin diferită. În cazul în care Număr
are o valoare de 0
, atunci, din punct de vedere tehnic, are o valoare, dar este testată dacă (someNumberThatEqualsZero)
va evalua la fals
. Pentru Număr
s puteți utiliza isNaN ()
pentru a determina dacă o valoare numerică valabilă este stocată într-o variabilă dată.
În orice caz, această tehnică este o metodă simplă de a evita eroarea. Dacă nu este setată variabila pe care dorim să efectuăm o operație, atunci nu efectuați operația. Dacă nu există băutură gustoasă în geamul nostru, nu ridicați geamul. Destul de simplu.
Dar această abordare este posibilă numai dacă logica este opțională. Dacă este necesară logica, probabil că puteți furniza o valoare implicită variabilei discutabile înainte de operația de eroare. De exemplu, dacă myArray
are potențialul de a fi nul
, dar este imperativ ca nu este, putem face acest lucru:
dacă (! myArray) myArray = []; myArray.push (someSprite.stage.align.toLowerCase ());
Acest lucru va verifica mai întâi pentru a vedea dacă este matricea nul
. Dacă este, inițializați-o într-o matrice goală (o matrice goală este o valoare validă. Poate fi goală, dar este o matrice și nu nul
) înainte de a executa linia controversată de cod. Dacă nu este nul
, sări direct la linia controversată de cod. În termeni reali, dacă paharul nostru este gol, umpleți-l cu o băutură gustoasă înainte de ao ridica.
În plus, dacă myArray
este o proprietate de instanță a clasei în care rulează această linie de cod, puteți asigura o valoare validă prin inițializarea proprietăților atunci când obiectul inițializează.
Ce se întâmplă dacă este necesară logica, dar variabila în cauză nu este atât de ușor sub controlul nostru? De exemplu, ce se întâmplă dacă linia noastră de coduri este necesară, dar variabila discutabilă este someSprite.stage
? Nu putem seta doar etapă
proprietate; care este controlat intern DisplayObject
și este citit doar pentru noi muritori. Apoi este posibil să aveți nevoie să vă lăsați vicioși și citiți următorul pas.
nul
etapăExistă probabil un număr infinit de scenarii în care o anumită variabilă sau o proprietate ar putea fi nul
. Evident, nu pot să le acoperez pe toate într-un sfat rapid. Există, totuși, o situație specifică care culminează din nou și din nou.
Să presupunem că scrieți un cod care arată astfel:
clasa publică QuickSprite extinde Sprite funcția publică QuickSprite () stage.addEventListener (MouseEvent.MOUSE_MOVE, onMove); funcția privată onMove (e: MouseEvent): void var culoare: ColorTransform = new ColorTransform (); color.color = stage.mouseX / stage.stageWidth * 0xFFFFFF; this.transform.colorTransform = culoare;
Un alt bit controversat de cod (care ar putea provoca convulsii - te consideri avertizat), dar în principiu ideea este că ai spiriduș
subclasa și ați setat această clasă pentru un clip pe scenă, utilizând Flash IDE.
Cu toate acestea, decideți că doriți să lucrați cu acestea QuickSprite
programat. Deci, încercați acest lucru:
var qs: QuickSprite = noul QuickSprite (); addChild (qs);
Și tu primești eroarea blestemată 1009. De ce? Pentru că în QuickSprite
constructor, accesați etapă
proprietate (moștenită de la DisplayObject
). Atunci când obiectul este creat în întregime cu cod, nu este pe scena la punctul în care rulează acea linie de cod, adică etapă
este nul
și veți obține eroarea. QuickSprite
se adaugă linia următoare, dar nu este destul de curând. Dacă instanța este creată prin tragerea unui simbol din bibliotecă și pe scenă, atunci există puțină magie la locul de muncă în spatele scenei, care asigură că instanța se află pe scenă (adică, etapă
proprietatea este setată) în timpul constructorului.
Deci, iată ce faceți: încercați pentru existența unei valori etapă
. În funcție de rezultat, puteți fie să rulați imediat codul de setare, fie să configurați un alt ascultător de evenimente pentru momentul în care acesta este QuickSprite
se adaugă la scenă. Ceva de genul:
funcția publică QuickSprite () if (stage) init (); altceva this.addEventListener (Event.ADDED_TO_STAGE, init); funcția privată init (e: Event = null) this.removeEventListener (Event.ADDED_TO_STAGE, init); stage.addEventListener (MouseEvent.MOUSE_MOVE, onMove);
Dacă mutăm etapă
line la o funcție diferită, și numim această funcție numai când avem o scenă, atunci suntem pregătiți. Dacă etapă
există de la început, mergeți mai departe și rulați init ()
imediat. Dacă nu, vom folosi init ()
ca funcție de ascultător pentru evenimente ADDED_TO_STAGE
, moment în care vom avea o valoare etapă și putem rula codul. Acum putem folosi clasa pentru conectarea la IDE Sprite sau complet programat.
Acest lucru funcționează bine și în clasele de documente. Când rulați un SWF singur, clasa de documente are acces imediat la etapă
. Dacă încărcați SWF într-un alt SWF, totuși, codul din stiva de inițializare a clasei de documente este executat înainte ca SWF-ul încărcat să fie adăugat pe ecran. Asemănător etapă
-verificarea trucului vă va permite să lucrați cu SWF atât ca piesă independentă, cât și ca un SWF încărcat într-un SWF care conține.
Vă mulțumim că ați citit acest sfat rapid! Sper că sunteți puțin luminat despre modul în care apare eroarea 1009 și cum puteți să o depanați. Rămâi acordat pentru mai multe sfaturi rapide despre alte erori comune.