Eine der häufigsten Fragen, die ich in Foren sehe und von Kollegen bekomme, ist das Debuggen von Fehler 1009, der auch als Nullobjektreferenzfehler bezeichnet wird. Oder, wie ich es nenne, der ärgerliche Mosquito Error From Hell. Es tritt viel auf, und leider enthält der Fehler selbst nicht viel Informationen über die Fehlerquelle. In diesem kurzen Tipp werfen wir einen Blick auf einige Schritte, die Sie unternehmen können, um diese Stechmücke aufzuspüren und gut zu zerquetschen.
Dieses Stück ist die erste Folge der allgemeineren Problembehebung in AS3. Tutorial. Wenn Sie einige der Techniken in diesem Tipp besser verstehen möchten, sollten Sie dies zunächst vollständig lesen.
Es ist zu schade, dass Adobe keine weiteren Informationen über die Wurzel dieses Fehlers bereitstellt (oder kann). Vor allem ist es ziemlich offen formuliert (ähnlich wie alle ihre Fehler, aber dies mehr als die meisten):
TypeError: Fehler # 1009: Kein Zugriff auf eine Eigenschaft oder Methode einer NULL-Objektreferenz
Versuchen wir, dies in alltäglicher Hinsicht auszudrücken. Fehler 1009 bedeutet, dass Sie versucht haben, etwas mit einer Variablen zu tun, von der Sie annehmen, dass sie einen Wert hat, aber wirklich nicht. Flash mag das nicht. Sie würden es auch nicht mögen; Stellen Sie sich vor, Sie hätten ein Glas, von dem Sie annahmen, dass es mit dem leckeren Getränk Ihrer Wahl voll war, aber wirklich leer war. Sie packen das Glas und erwarten einen erfrischenden Schluck, aber Sie fühlen stattdessen das enttäuschende Gewicht eines leeren Glases. Das ist Ihr persönlicher Fehler 1009.
Wenn Sie dies in ActionScript tun:
var s: String; trace (s.toUpperCase ());
Flash brennt hart (ein technischer Begriff für "Fehler erzeugen"), wenn Sie den Code ausführen. Die Variable s
Möglicherweise wurde deklariert, aber sein Wert ist Null
(wir setzen niemals den Wert, haben nur die Variable deklariert), also den Aufruf von toUpperCase
Methode darauf ist mühsam.
Um klar zu sein, weil s
wird als a deklariert String
, das Compiler nimmt kein Problem mit dem Code auf: Es wird eine Variable aufgerufen s
, es ist ein String
, und toUpperCase
ist eine gültige Methode zum Aufruf String
s. Der Fehler, den wir erhalten, ist a Laufzeit Fehler, was bedeutet, dass wir es nur erhalten, wenn wir die SWF-Datei ausführen. Erst wenn die Logik ausgeführt wird, können wir jetzt sehen, wie sich dies herausstellt.
Wie bei jedem Laufzeitfehler ist es manchmal ziemlich einfach, ohne zusätzliche Informationen den Vorgang zu erkennen. In anderen Fällen ist es hilfreich, dies weiter einzugrenzen. Aktivieren Sie an diesem Punkt "Debugging zulassen". Wenn diese Option aktiviert ist, erhalten Sie Fehler, die auch Zeilennummern enthalten. Alternativ können Sie in der Lage sein, Film zu debuggen. indem Sie die Tastenkombination Befehl-Umschalt-Zurück-Taste / Strg-Umschalt-Eingabe drücken.
Siehe dazu den allgemeinen Debugging-Tipps-Artikel? Beheben von Fehlern in AS3?
Manchmal reicht das aus. Wenn Sie die bestimmte Zeile kennen, können Sie alle Informationen benötigen, die Sie benötigen. Wenn nicht, werden wir im nächsten Schritt etwas tiefer graben.
Unser lieber Redakteur Michael James Williams hat den Punkt dieses Schrittes in einem Limerick zusammengefasst, den ich Ihnen jetzt mit seiner freundlichen Erlaubnis vorstellen möchte:
AS3-Fehler ein-oh-oh-neun
Ist nie ein sehr gutes Zeichen.
Kein Grund zur Besorgnis,
Drücken Sie Strg-Umschalttaste-Return
Und es wird die Ursache (naja, die Linie).
Wenn Sie die fehlerhafte Zeile gefunden haben, sich aber noch nicht sicher sind, was los ist, wählen Sie die Zeile aus. Nehmen Sie jede Variable in dieser Zeile und verfolgen Sie sie vor der Fehler.
Da der Fehler beim Zugriff auf eine Eigenschaft oder beim Aufruf einer Methode für eine Nullvariable auftritt, sollten Sie zur Abdeckung Ihrer Basen alle Variablen und Eigenschaften verfolgen, auf die unmittelbar ein Punkt folgt. Nehmen Sie zum Beispiel diese Codezeile:
myArray.push (someSprite.stage.align.toLowerCase ());
Zugegeben, das ist ein ziemlich erfundener Code, für den ich mir keine praktische Verwendung vorstellen kann, aber Sie sollten das herausfinden vier gesamt möglich Null
Werte, auf die mit dem Punkt zugegriffen wird:
myArray
: wir nennen das drücken
Methode für diese VariableSomeSprite
: wir greifen auf die Bühne
EigentumBühne
: wir greifen auf die ausrichten
Eigentumausrichten
: wir nennen das toLowerCase
MethodeIhr Debugging-Code könnte also folgendermaßen aussehen:
trace ("meinArray:", meinArray); trace ("someSprite:", someSprite); trace ("someSprite.stage:", someSprite.stage); trace ("someSprite.stage.align:", someSprite.stage.align);
Ordnung ist wichtig; ob SomeSprite
ist das Nullobjekt, aber Sie testen nach someSprite.stage.align
vor dem Testen für SomeSprite
, Sie haben weniger definitive Ergebnisse.
Nun spielt auch der gesunde Menschenverstand in diese Richtung. In meinem Beispiel, wenn Bühne
existiert also ausrichten
wird am sichersten einen Wert haben; das Bühne
hat immer eine ausrichten
Einstellung, auch wenn es der Standardwert ist.
Normalerweise sehen Sie Folgendes:
myArray: [? Sachen im Array? someSprite: [object Sprite] someSprite.stage: null Fehler # 1009:?
Was solltest du in dem der Bühne
Eigentum ist Null
, und jetzt können Sie es reparieren.
Die einfachste Lösung besteht darin, die beleidigende Aussage in einem block und führe den Block nur aus, wenn die betreffende Variable nicht null ist. Angenommen, in unserem vorherigen Beispiel war dies tatsächlich der Fall Bühne
das war Null
, Wir könnten so etwas machen:
if (someSprite.stage) myArray.push (someSprite.stage.align.toLowerCase ());
Dieser Test - if (someSprite.stage)
- wird zurückkehren wahr
wenn es einen Wert gibt (unabhängig vom Wert), und falsch
wenn es Null
. Im Allgemeinen funktioniert diese Notation; Sie können immer verwenden if (someSprite.stage! = null)
wenn es dir lieber ist. Nummer
Die Situation ist jedoch etwas anders. Wenn die Nummer
hat einen Wert von 0
, dann hat es technisch einen wert, aber prüfend if (someNumberThatEqualsZero)
wird zu bewerten falsch
. Zum Nummer
s können Sie die verwenden isNaN ()
Funktion, um festzustellen, ob ein gültiger numerischer Wert in einer bestimmten Variablen gespeichert ist.
In jedem Fall ist diese Technik eine einfache Möglichkeit, den Fehler zu umgehen. Wenn die Variable, für die eine Operation ausgeführt werden soll, nicht festgelegt ist, führen Sie die Operation nicht aus. Wenn sich kein leckeres Getränk in unserem Glas befindet, heben Sie das Glas nicht auf. Einfach genug.
Dieser Ansatz ist jedoch nur möglich, wenn die Logik optional ist. Wenn die Logik erforderlich ist, können Sie der fraglichen Variablen vor der Fehleroperation möglicherweise einen Standardwert zuweisen. Zum Beispiel wenn myArray
hat das Potenzial zu sein Null
, Es ist jedoch unerlässlich, dass dies nicht der Fall ist. Wir können dies tun:
if (! meinArray) meinArray = []; myArray.push (someSprite.stage.align.toLowerCase ());
Zuerst wird geprüft, ob das Array vorhanden ist Null
. Wenn ja, initialisieren Sie es mit einem leeren Array (ein leeres Array ist ein gültiger Wert. Er kann leer sein, aber es ist ein Array und nicht) Null
), bevor die programmierte Codezeile ausgeführt wird. Wenn es nicht so ist Null
, springen Sie direkt zur Codezeile. Wenn unser Glas leer ist, füllen Sie es mit einem leckeren Getränk, bevor Sie es abholen.
Darüber hinaus wenn myArray
Ist eine Instanzeigenschaft der Klasse, in der diese Codezeile ausgeführt wird. Sie können einen gültigen Wert ziemlich sicher sicherstellen, indem Sie Ihre Eigenschaften bei der Initialisierung des Objekts initialisieren.
Was ist, wenn die Logik erforderlich ist, die fragliche Variable jedoch nicht so leicht unter unserer Kontrolle steht? Was ist beispielsweise, wenn unsere erfundene Codezeile erforderlich ist, die fragliche Variable jedoch SomeSprite.stage
? Wir können das nicht einfach einstellen Bühne
Eigentum; das wird intern gesteuert DisplayObject
und ist für uns nur Sterbliche schreibgeschützt. Dann müssen Sie sich vielleicht schlau machen und den nächsten Schritt lesen.
Null
BühneEs gibt wahrscheinlich unendlich viele Szenarien, in denen eine bestimmte Variable oder Eigenschaft vorhanden sein könnte Null
. Natürlich kann ich nicht alle in einem Quick Tip behandeln. Es gibt jedoch eine bestimmte Situation, die immer wieder auftaucht.
Angenommen, Sie schreiben Code, der so aussieht:
public class QuickSprite erweitert Sprite public function QuickSprite () stage.addEventListener (MouseEvent.MOUSE_MOVE, onMove); private Funktion onMove (e: MouseEvent): void var color: ColorTransform = neu ColorTransform (); color.color = stage.mouseX / stage.stageWidth * 0xFFFFFF; this.transform.colorTransform = Farbe;
Ein weiteres Stück Code (der Anfälle auslösen könnte - betrachten Sie sich als gewarnt), aber im Grunde geht es darum, dass Sie einen haben Sprite
Unterklasse und Sie legen dies als Klasse für einen Clip auf der Bühne fest, indem Sie die Flash-IDE verwenden.
Sie entscheiden jedoch, dass Sie mit diesen arbeiten möchten QuickSprite
s programmatisch. Also versuchst du das:
var qs: QuickSprite = new QuickSprite (); addChild (qs);
Und Sie erhalten den verfluchten Fehler 1009. Warum? Weil in der QuickSprite
Konstruktor greifen Sie auf die Bühne
property (geerbt von DisplayObject
). Wenn das Objekt vollständig mit Code erstellt wird, befindet es sich nicht an der Stelle, an der diese Codezeile ausgeführt wird Bühne
ist Null
und du bekommst den Fehler. Das QuickSprite
wird die nächste Zeile hinzugefügt, aber es ist nicht früh genug. Wenn die Instanz erstellt wird, indem ein Symbol aus der Bibliothek auf die Bühne gezogen wird, wirkt hinter den Kulissen ein wenig Magie, die dafür sorgt, dass sich die Instanz auf der Bühne befindet Bühne
Eigenschaft wird während des Konstruktors gesetzt.
Also, was Sie tun: Sie testen, ob ein Wert vorhanden ist Bühne
. Je nach Ergebnis können Sie den Setup-Code entweder sofort ausführen oder einen anderen Ereignis-Listener für den Zeitpunkt einrichten QuickSprite
wird der Bühne hinzugefügt. Etwas wie das:
public function QuickSprite () if (stage) init (); else this.addEventListener (Event.ADDED_TO_STAGE, init); private Funktion init (e: Event = null) this.removeEventListener (Event.ADDED_TO_STAGE, init); stage.addEventListener (MouseEvent.MOUSE_MOVE, onMove);
Wenn wir das bewegen Bühne
Zeile zu einer anderen Funktion, und rufen Sie diese Funktion nur auf, wenn wir eine Stufe haben, dann sind wir eingestellt. Ob Bühne
existiert von Anfang an, gehen Sie voran und laufen Sie drin()
jetzt sofort. Wenn nicht, verwenden wir drin()
als Event-Listener-Funktion für ADDED_TO_STAGE
, An diesem Punkt haben wir einen Wert für die Stufe und können den Code ausführen. Jetzt können wir die Klasse für die Verbindung zu IDE Sprite oder vollständig programmgesteuert verwenden.
Dies funktioniert auch in Dokumentenklassen. Wenn Sie eine SWF-Datei selbst ausführen, hat die Dokumentenklasse sofortigen Zugriff auf diese Bühne
. Wenn Sie diese SWF-Datei jedoch in eine andere SWF-Datei laden, wird der Code im Initialisierungsstapel der Dokumentklasse ausgeführt, bevor die geladene SWF-Datei der Anzeige hinzugefügt wird. Ein ähnliches Bühne
-Wenn Sie den Trick überprüfen, können Sie mit der SWF-Datei sowohl als eigenständige als auch als SWF-Datei arbeiten, die in eine SWF-Datei geladen wird.
Vielen Dank für das Lesen dieses Kurztipps! Ich hoffe, Sie werden ein wenig darüber aufgeklärt, wie Fehler 1009 auftritt und wie Sie ihn debuggen können. Bleiben Sie dran für weitere Schnelltipps zu anderen häufig auftretenden Fehlern.