ActionScript 3
Förstå "Fel 1009: Kan inte komma åt en egenskap eller metod för en referens till nollobjekt"
Sök…
Introduktion
null
. Exemplen som presenteras visar olika fall där detta fel uppstår, tillsammans med några rekommendationer om hur man kan mildra felet.
Anmärkningar
Det fruktade och ofta frågade "Fel 1009: Kan inte komma åt en egenskap eller metod för en nollobjektreferens" är en signal om att en del av uppgifterna verkar som noll, men försöks användas som ett bebodd objekt. Det finns ganska många typer av problem som kan orsaka detta beteende, och var och en bör testas mot koden där felet uppstod.
Scenen är inte tillgänglig
Ibland skriver utvecklare någon kod som önskar åtkomst till stage
, eller Flash-scenen, för att lägga till lyssnare. Det kan fungera för första gången, då plötsligt misslyckas med att fungera och producera felet 1009. Koden i fråga kan till och med vara på tidslinjen, eftersom det är det första initiativet att lägga till kod där, och många lektioner som fortfarande finns använder tidslinjekodlager för att placera koden.
public class Main extends MovieClip {
public function Main() {
stage.addEventListener(Event.ENTER_FRAME,update); // here
Anledningen till att denna kod inte fungerar är enkel: Ett visningsobjekt instanseras först, läggs sedan till i visningslistan, och medan det är av visningslistan är stage
noll.
Värre om koden så här:
stage.addEventListener(Event.ENTER_FRAME,update); // here
placeras på tidslinjen. Det kan även arbeta under en längre tid, medan Main
objektet slog till steg via GUI. Sedan laddas deras SWF från en annan SWF, och plötsligt bryts koden. Detta händer eftersom Main
ramar är konstruerade på ett annat sätt när SWF laddas direkt av spelaren och när lastningen behandlas asynkront. Lösningen är att använda Event.ADDED_TO_STAGE
lyssnare och lägga all kod som adresserar scenen i den och lägga lyssnaren i en AS-fil istället för tidslinjen.
Ogiltig typecast
function listener(e:Event):void {
var m:MovieClip=e.target as MovieClip;
m.x++;
}
Om en sådan lyssnare är kopplad till ett objekt som inte är en MovieClip
efterkommer (till exempel en Sprite
), kommer typecasten att misslyckas, och eventuella efterföljande operationer med dess resultat kommer att kasta 1009-felet.
Oinstantierat objekt
var a:Object;
trace(a); // null
trace(a.b); // Error 1009
Här förklaras en objektreferens, men tilldelas aldrig ett värde, vare sig det är med new
eller tilldelar ett icke-nollvärde. Att begära dess egenskaper eller metod resulterar i ett 1009-fel.
Flerskiktat uttryck
x=anObject.aProperty.anotherProperty.getSomething().data;
Här kan alla objekt innan punkten hamna vara noll, och att använda metoder som returnerar komplexa objekt ökar bara komplikationen för att felsöka nollfelet. Värsta fall om metoden är benägen att främmande fel, säg hämta data över nätverket.
Obehandlat funktionsresultat
s=this.getChildByName("garbage");
if (s.parent==this) {...}
getChildByName()
är en av de många funktioner som kan returnera noll om ett fel inträffade vid bearbetning av dess ingång. Därför, om du får ett objekt från någon funktion som eventuellt kan returnera null, kontrollera först om null. Här fråges en egenskap omedelbart utan att först kontrollera om s
är noll, detta kommer att generera 1009-felet.
Glömt händelse lyssnare
addEventListener(Event.ENTER_FRAME,moveChild);
function moveChild(e:Event):void {
childMC.x++;
if (childMC.x>1000) {
gotoAndStop(2);
}
}
Detta exempel kommer att flytta childMC
(läggs till i Main
vid designtid) men kastar omedelbart en 1009 så snart gotoAndStop()
påkallas, om det childMC
inte finns i ram 2. Det främsta skälet till detta är att när en playhead passerar en nyckelram (en ram som inte ärver den föregående rams objektuppsättning), antingen genom att använda gotoAndStop()
, gotoAndPlay()
med destinationsram som separeras från den aktuella ramen med en nyckelram eller genom normal uppspelning om SWF är en animering, den nuvarande rams innehåll förstörs och det nya innehållet skapas med hjälp av data lagrade från GUI. Så, om den nya ramen inte har ett barn som heter childMC
, kommer fastighetsbegäran att returneras noll och 1009 kastas.
Samma princip gäller om du lägger till två händelselister, men tar bort bara en eller lägger till en lyssnare till ett objekt, men försöker ta bort från ett annat. Det removeEventListener
samtalet kommer inte att varna dig om objektet inte hade en respektive händelse lyssnare bifogad, så läs koden som lägger till och tar bort händelselisterna noggrant.
Observera också: Att använda Timer
, ringa setInterval()
och setTimeout()
skapar också händelselister, och dessa bör också rensas ordentligt.
Ogiltig hänvisning till ett rambaserat objekt
Ibland gotoAndStop()
i mitten av koden som hänvisar till vissa rambaserade egenskaper. Men strax efter att ramen har ändrats ogiltigförklaras alla länkar till egenskaper som fanns i den aktuella ramen, så all behandling som involverar dem bör omedelbart avslutas.
Det finns två allmänna scenarier för en sådan bearbetning: För det första slutar en slinga inte efter gotoAndStop()
, som här:
for each (bullet in bullets) {
if (player.hitTestObject(bullet)) gotoAndStop("gameOver");
}
Här innebär ett 1009-fel att player
MC förstördes under behandling av gotoAndStop()
, men slingan fortsätter och hänvisar till länken nu-null för att få hitTestObject()
från. Om villkoret skulle säga if (bullet.hitTestObject(player))
istället skulle felet vara # 2007 "Parameter hitTestObject får inte vara noll". Lösningen är att sätta en return
uttalande direkt efter ringer gotoAndStop()
.
Det andra fallet är flera händelser lyssnar på samma evenemang. Så här:
stage.addEventListener(Event.ENTER_FRAME,func1);
stage.addEventListener(Event.ENTER_FRAME,func2);
function func1(e:Event):void {
if (condition()) {
gotoAndStop(2);
}
}
Om condition()
är sant, skulle den första lyssnaren utföra gotoAndStop()
, men den andra lyssnaren kommer fortfarande att köras, och om den hänvisar till objekt i ramen kastas ett 1009-fel. Lösningen är att undvika flera lyssnare på en enda händelse, i ett enda objekt är det bättre att ha en lyssnare som hanterar alla situationer på den händelsen och som kan ordentligt avslutas om en ramändring behövs.