Mein Swift-Programm stürzt mit EXC_BAD_INSTRUCTION
einem der folgenden ähnlichen Fehler ab. Was bedeutet dieser Fehler und wie behebe ich ihn?
Schwerwiegender Fehler: Beim Auspacken eines optionalen Werts wurde unerwartet Null gefunden
oder
Schwerwiegender Fehler: Unerwartet wurde Null gefunden, während implizit ein optionaler Wert entpackt wurde
Dieser Beitrag soll Antworten auf "unerwartet gefundene Null" -Probleme sammeln, damit sie nicht verstreut und schwer zu finden sind. Fühlen Sie sich frei, Ihre eigene Antwort hinzuzufügen oder die vorhandene Wiki-Antwort zu bearbeiten .
swift
exception
error-handling
pkamb
quelle
quelle
Antworten:
Diese Antwort ist Community-Wiki . Wenn Sie der Meinung sind, dass es besser gemacht werden könnte, können Sie es jederzeit bearbeiten !
Hintergrund: Was ist optional?
In Swift
Optional
ist dies ein generischer Typ , der einen Wert (jeglicher Art) oder überhaupt keinen Wert enthalten kann.In vielen anderen Programmiersprachen wird häufig ein bestimmter "Sentinel" -Wert verwendet, um auf das Fehlen eines Werts hinzuweisen . In Objective-C zeigt beispielsweise
nil
(der Nullzeiger ) das Fehlen eines Objekts an. Bei der Arbeit mit primitiven Typen wird dies jedoch schwieriger. Sollte-1
dies verwendet werden, um das Fehlen einer Ganzzahl oder vielleichtINT_MIN
einer anderen Ganzzahl anzuzeigen ? Wenn ein bestimmter Wert als "keine Ganzzahl" ausgewählt wird, bedeutet dies, dass er nicht mehr als gültiger Wert behandelt werden kann.Swift ist eine typsichere Sprache, dh die Sprache hilft Ihnen dabei, klar zu machen, mit welchen Arten von Werten Ihr Code arbeiten kann. Wenn ein Teil Ihres Codes einen String erwartet, verhindert die Typensicherheit, dass Sie ihm versehentlich einen Int übergeben.
In Swift kann jeder Typ optional gemacht werden . Ein optionaler Wert kann einen beliebigen Wert des ursprünglichen Typs oder des speziellen Werts annehmen
nil
.Optionale Optionen werden mit einem
?
Suffix für den Typ definiert:Das Fehlen eines Wertes in einem optionalen wird angezeigt durch
nil
:(Beachten Sie, dass dies
nil
nicht mit demnil
in Objective-C identisch ist . In Objective-Cnil
fehlt ein gültiger Objektzeiger . In Swift sind Optionals nicht auf Objekte / Referenztypen beschränkt. Optional verhält es sich ähnlich wie Haskell's Maybe .)Warum wurde " schwerwiegender Fehler: Beim Auspacken eines optionalen Werts unerwartet Null gefunden" angezeigt ?
Um auf den Wert eines optionalen Elements zuzugreifen (falls überhaupt vorhanden), müssen Sie ihn auspacken . Ein optionaler Wert kann sicher oder gewaltsam ausgepackt werden. Wenn Sie eine Option zwangsweise auspacken und sie keinen Wert hat, stürzt Ihr Programm mit der obigen Meldung ab.
Xcode zeigt Ihnen den Absturz an, indem Sie eine Codezeile markieren. Das Problem tritt in dieser Zeile auf.
Dieser Absturz kann mit zwei verschiedenen Arten des Force-Unwraps auftreten:
1. Explizite Force-Entpackung
Dies erfolgt mit dem
!
Bediener optional. Zum Beispiel:Wie
anOptionalString
istnil
hier, Sie werden einen Absturz auf der Linie, wo Sie unwrap es erzwingen.2. Implizit ausgepackte Optionen
Diese werden
!
eher mit einem als mit einem?
nach dem Typ definiert.Es wird angenommen, dass diese Optionen einen Wert enthalten. Wenn Sie daher auf eine implizit entpackte Option zugreifen, wird diese automatisch für Sie erzwungen. Wenn es keinen Wert enthält, stürzt es ab.
Um herauszufinden, welche Variable den Absturz verursacht hat, können Sie gedrückt halten, ⌥während Sie auf klicken, um die Definition anzuzeigen, in der Sie möglicherweise den optionalen Typ finden.
Insbesondere IBOutlets sind normalerweise implizit ausgepackte Optionen. Dies liegt daran, dass Ihr xib oder Storyboard die Outlets nach der Initialisierung zur Laufzeit verbindet . Sie sollten daher sicherstellen, dass Sie nicht auf Outlets zugreifen, bevor diese geladen werden. Sie sollten auch überprüfen, ob die Verbindungen in Ihrer Storyboard- / XIB-Datei korrekt sind. Andernfalls werden die Werte
nil
zur Laufzeit angezeigt und stürzen daher ab, wenn sie implizit entpackt werden . Versuchen Sie beim Reparieren von Verbindungen, die Codezeilen zu löschen, die Ihre Steckdosen definieren, und verbinden Sie sie dann erneut.Wann sollte ich jemals ein optionales Auspacken erzwingen?
Explizite Force-Entpackung
In der Regel sollten Sie niemals explizit das Entpacken einer Option mit dem
!
Operator erzwingen . Es kann Fälle geben, in denen die Verwendung!
akzeptabel ist. Sie sollten sie jedoch nur verwenden, wenn Sie zu 100% sicher sind, dass die Option einen Wert enthält.Es kann zwar vorkommen, dass Sie das Entpacken mit Gewalt anwenden können, da Sie wissen , dass ein optionales Element einen Wert enthält - es gibt jedoch keinen einzigen Element Ort, an dem Sie dieses optionale Element nicht sicher auspacken können.
Implizit ausgepackte Optionen
Diese Variablen sind so konzipiert, dass Sie ihre Zuordnung bis zu einem späteren Zeitpunkt in Ihrem Code verschieben können. Es liegt in Ihrer Verantwortung, sicherzustellen, dass sie einen Wert haben, bevor Sie darauf zugreifen. Da es sich jedoch um ein gewaltsames Auspacken handelt, sind sie von Natur aus immer noch unsicher, da davon ausgegangen wird, dass Ihr Wert nicht Null ist, obwohl die Zuweisung von Null gültig ist.
Sie sollten nur implizit entpackte Optionen als letzten Ausweg verwenden . Wenn Sie eine verzögerte Variable verwenden oder einen Standardwert für eine Variable angeben können, sollten Sie dies tun, anstatt eine implizit entpackte Option zu verwenden.
Es gibt jedoch einige Szenarien, in denen implizit ausgepackte Optionen von Vorteil sind , und Sie können weiterhin verschiedene Methoden zum sicheren Auspacken verwenden, wie unten aufgeführt. Sie sollten sie jedoch immer mit der gebotenen Vorsicht verwenden.
Wie kann ich sicher mit Optionals umgehen?
Der einfachste Weg, um zu überprüfen, ob ein optionales Element einen Wert enthält, besteht darin, ihn mit zu vergleichen
nil
.In 99,9% der Fälle, in denen Sie mit Optionen arbeiten, möchten Sie tatsächlich auf den darin enthaltenen Wert zugreifen, sofern dieser überhaupt einen enthält. Dazu können Sie die optionale Bindung verwenden .
Optionale Bindung
Mit der optionalen Bindung können Sie überprüfen, ob eine Option einen Wert enthält - und den nicht umschlossenen Wert einer neuen Variablen oder Konstante zuweisen. Es verwendet die Syntax
if let x = anOptional {...}
oderif var x = anOptional {...}
, je nachdem, ob Sie den Wert der neuen Variablen nach dem Binden ändern müssen.Zum Beispiel:
Überprüfen Sie zunächst, ob das optionale Element einen Wert enthält. Wenn dies der Fall ist , wird der Wert "entpackt" einer neuen Variablen (
number
) zugewiesen, die Sie dann frei verwenden können, als wäre sie nicht optional. Wenn das optionale Element keinen Wert enthält, wird die else-Klausel wie erwartet aufgerufen.Das Schöne an der optionalen Bindung ist, dass Sie mehrere Optionen gleichzeitig auspacken können. Sie können die Anweisungen einfach durch ein Komma trennen. Die Anweisung ist erfolgreich, wenn alle Optionen ausgepackt wurden.
Ein weiterer guter Trick ist, dass Sie auch Kommas verwenden können, um nach dem Auspacken nach einer bestimmten Bedingung für den Wert zu suchen.
Der einzige Haken bei der Verwendung der optionalen Bindung in einer if-Anweisung besteht darin, dass Sie nur innerhalb des Bereichs der Anweisung auf den nicht umschlossenen Wert zugreifen können. Wenn Sie außerhalb des Gültigkeitsbereichs der Anweisung Zugriff auf den Wert benötigen, können Sie eine Guard-Anweisung verwenden .
Mit einer Guard-Anweisung können Sie eine Bedingung für den Erfolg definieren. Der aktuelle Bereich wird nur dann weiter ausgeführt, wenn diese Bedingung erfüllt ist. Sie werden mit der Syntax definiert
guard condition else {...}
.Um sie mit einer optionalen Bindung zu verwenden, können Sie Folgendes tun:
(Beachten Sie, dass innerhalb des Schutzkörpers, Sie müssen eine der Verwendung Steuertransferanweisungen , um den Umfang des aktuell ausgeführten Code zu verlassen).
Wenn es
anOptionalInt
einen Wert enthält, wird dieser entpackt und der neuennumber
Konstante zugewiesen . Der Code nach dem Guard wird dann weiter ausgeführt. Wenn es keinen Wert enthält, führt der Guard den Code in den Klammern aus, was zur Übertragung der Kontrolle führt, sodass der Code unmittelbar danach nicht ausgeführt wird.Das Schöne an Guard-Anweisungen ist, dass der nicht umschlossene Wert jetzt in Code verwendet werden kann, der auf die Anweisung folgt (da wir wissen, dass zukünftiger Code nur ausgeführt werden kann , wenn das optionale einen Wert hat). Dies ist ideal, um "Pyramiden des Untergangs" zu beseitigen. die durch das Verschachteln mehrerer if-Anweisungen entstehen.
Zum Beispiel:
Guards unterstützen auch dieselben netten Tricks wie die if-Anweisung, z. B. das gleichzeitige Auspacken mehrerer Optionen und die Verwendung der
where
Klausel.Egal , ob Sie eine if oder Schutzerklärung verwenden , hängt vollständig ab , ob ein künftiges Code erfordert die optionalen Wert enthalten.
Null-Koaleszenz-Operator
Der Nil Coalescing Operator ist eine raffinierte Kurzversion des ternären bedingten Operators , der hauptsächlich zum Konvertieren von Optionen in Nicht-Optionen entwickelt wurde. Es hat die Syntax
a ?? b
, wobeia
es sich um einen optionalen Typ handelt undb
derselbe Typ ist wiea
(obwohl normalerweise nicht optional).Sie können im Wesentlichen sagen: „Wenn
a
ein Wert enthalten ist, packen Sie ihn aus. Wenn dies nicht der Fall ist, kehren Sieb
stattdessen zurück. “ Zum Beispiel könnten Sie es so verwenden:Dadurch wird eine
number
Konstante vomInt
Typ definiert, die entweder den Wert vonanOptionalInt
enthält, wenn sie einen Wert enthält, oder auf0
andere Weise.Es ist nur eine Abkürzung für:
Optionale Verkettung
Sie können die optionale Verkettung verwenden, um eine Methode aufzurufen oder auf eine optionale Eigenschaft zuzugreifen. Dies erfolgt einfach durch Suffixieren des Variablennamens mit a
?
bei Verwendung .Angenommen, wir haben eine Variable
foo
vom Typ einer optionalenFoo
Instanz.Wenn wir eine Methode aufrufen wollten
foo
, die nichts zurückgibt, können wir einfach Folgendes tun:Wenn
foo
ein Wert enthalten ist, wird diese Methode darauf aufgerufen. Wenn dies nicht der Fall ist, passiert nichts Schlimmes - der Code wird einfach weiter ausgeführt.(Dies ähnelt dem Senden von Nachrichten an
nil
Objective-C.)Dies kann daher auch zum Festlegen von Eigenschaften sowie von Aufrufmethoden verwendet werden. Zum Beispiel:
Auch hier wird nichts Schlimmes passieren, wenn es so
foo
istnil
. Ihr Code wird einfach weiter ausgeführt.Ein weiterer nützlicher Trick, den Sie mit der optionalen Verkettung ausführen können, besteht darin, zu überprüfen, ob das Festlegen einer Eigenschaft oder das Aufrufen einer Methode erfolgreich war. Sie können dies tun, indem Sie den Rückgabewert mit vergleichen
nil
.(Dies liegt daran, dass ein optionaler Wert zurückgegeben wird
Void?
und nichtVoid
für eine Methode, die nichts zurückgibt.)Zum Beispiel:
Beim Versuch, auf Eigenschaften zuzugreifen oder Methoden aufzurufen, die einen Wert zurückgeben, wird es jedoch etwas schwieriger. Da dies
foo
optional ist, ist alles, was von ihm zurückgegeben wird, ebenfalls optional. Um dies zu beheben, können Sie entweder die zurückgegebenen Optionen mit einer der oben genannten Methoden auspacken oder sichfoo
selbst auspacken , bevor Sie auf Methoden zugreifen oder Methoden aufrufen, die Werte zurückgeben.Wie der Name schon sagt, können Sie diese Anweisungen auch miteinander verketten. Dies bedeutet, dass Sie, wenn Sie
foo
eine optionale Eigenschaft habenbaz
, die eine Eigenschaftqux
hat, Folgendes schreiben können:Da
foo
undbaz
optional sind, ist der von zurückgegebene Wertqux
immer optional, unabhängig davon, ob erqux
selbst optional ist.map
undflatMap
Eine häufig nicht ausreichend genutzte Funktion mit Optionen ist die Möglichkeit, die Funktionen
map
und zuflatMap
verwenden. Mit diesen können Sie nicht optionale Transformationen auf optionale Variablen anwenden. Wenn ein optionales Element einen Wert hat, können Sie eine bestimmte Transformation darauf anwenden. Wenn es keinen Wert hat, bleibt esnil
.Angenommen, Sie haben eine optionale Zeichenfolge:
Durch Anwenden der
map
Funktion darauf können wir diestringByAppendingString
Funktion verwenden, um sie mit einer anderen Zeichenfolge zu verketten.Da
stringByAppendingString
ein nicht optionales Zeichenfolgenargument verwendet wird, können wir unsere optionale Zeichenfolge nicht direkt eingeben. Mit usingmap
können wir jedoch allowstringByAppendingString
verwenden, wennanOptionalString
ein Wert vorhanden ist.Zum Beispiel:
Wenn
anOptionalString
jedoch kein Wert vorhanden ist,map
wird zurückgegebennil
. Zum Beispiel:flatMap
funktioniert ähnlich wiemap
, außer dass Sie eine weitere Option innerhalb des Verschlusskörpers zurückgeben können. Dies bedeutet, dass Sie eine Option in einen Prozess eingeben können, für den eine nicht optionale Eingabe erforderlich ist, eine Option jedoch selbst ausgeben kann.try!
Das Fehlerbehandlungssystem von Swift kann sicher mit Do-Try-Catch verwendet werden :
Wenn
someThrowingFunc()
ein Fehler ausgelöst wird, wird der Fehler sicher imcatch
Block abgefangen .Die
error
Konstante, die Sie imcatch
Block sehen, wurde von uns nicht deklariert - sie wird automatisch von generiertcatch
.Sie können sich auch
error
selbst deklarieren , es hat den Vorteil, dass Sie es in ein nützliches Format umwandeln können, zum Beispiel:Auf
try
diese Weise können Sie Fehler von Wurffunktionen versuchen, abfangen und behandeln.Es gibt auch,
try?
was den Fehler absorbiert:Das Fehlerbehandlungssystem von Swift bietet jedoch auch eine Möglichkeit, den Versuch zu erzwingen
try!
:Die in diesem Beitrag erläuterten Konzepte gelten auch hier: Wenn ein Fehler ausgegeben wird, stürzt die Anwendung ab.
Sie sollten es nur verwenden,
try!
wenn Sie nachweisen können, dass das Ergebnis in Ihrem Kontext niemals fehlschlägt - und dies ist sehr selten.Meistens verwenden Sie das komplette Do-Try-Catch-System - und das optionale
try?
- in den seltenen Fällen, in denen die Behandlung des Fehlers nicht wichtig ist.Ressourcen
quelle
compactMap()
anstelle von zu verwendenflatMap()
.TL; DR Antwort
Mit sehr wenigen Ausnahmen ist diese Regel golden:
Vermeiden Sie die Verwendung von
!
Deklarieren Sie die Variable optional (
?
), nicht implizit entpackte Optionals (IUO) (!
)Mit anderen Worten, verwenden Sie lieber:
var nameOfDaughter: String?
Anstatt:
var nameOfDaughter: String!
Entpacken Sie die optionale Variable mit
if let
oderguard let
Entweder die Variable wie folgt auspacken:
Oder so:
Diese Antwort sollte prägnant sein, zum vollständigen Verständnis die akzeptierte Antwort lesen
Ressourcen
quelle
Diese Frage taucht die ganze Zeit bei SO auf. Es ist eines der ersten Dinge, mit denen neue Swift-Entwickler zu kämpfen haben.
Hintergrund:
Swift verwendet das Konzept der "Optionals", um mit Werten umzugehen, die einen Wert enthalten können oder nicht. In anderen Sprachen wie C können Sie den Wert 0 in einer Variablen speichern, um anzuzeigen, dass sie keinen Wert enthält. Was ist jedoch, wenn 0 ein gültiger Wert ist? Dann könnten Sie -1 verwenden. Was ist, wenn -1 ein gültiger Wert ist? Und so weiter.
Mit Swift-Optionen können Sie eine Variable eines beliebigen Typs so einrichten, dass sie entweder einen gültigen Wert oder keinen Wert enthält.
Sie setzen ein Fragezeichen nach dem Typ, wenn Sie eine Variable als Mittelwert deklarieren (Typ x oder kein Wert).
Ein optionales Element ist tatsächlich ein Container, der entweder eine Variable eines bestimmten Typs oder nichts enthält.
Ein optionales Element muss "ausgepackt" werden, um den darin enthaltenen Wert abzurufen.
Das "!" operator ist ein "Force Unwrap" -Operator. Es heißt "Vertrau mir. Ich weiß, was ich tue. Ich garantiere, dass die Variable bei der Ausführung dieses Codes kein Null enthält." Wenn Sie sich irren, stürzen Sie ab.
Vermeiden Sie das "!", Wenn Sie nicht wirklich wissen , was Sie tun. Bediener zum Auspacken zwingen. Es ist wahrscheinlich die größte Absturzquelle für Anfänger von Swift-Programmierern.
Umgang mit Optionen:
Es gibt viele andere Möglichkeiten, mit Optionen umzugehen, die sicherer sind. Hier sind einige (keine vollständige Liste)
Sie können "optionale Bindung" oder "if let" verwenden, um zu sagen, "wenn diese Option einen Wert enthält, speichern Sie diesen Wert in einer neuen, nicht optionalen Variablen. Wenn die Option keinen Wert enthält, überspringen Sie den Hauptteil dieser if-Anweisung ".
Hier ist ein Beispiel für eine optionale Bindung mit unserem
foo
optionalen:Beachten Sie, dass die Variable, die Sie definieren, wenn Sie optionales Biding verwenden, nur im Hauptteil der if-Anweisung vorhanden ist (nur "im Gültigkeitsbereich" ist).
Alternativ können Sie eine Guard-Anweisung verwenden, mit der Sie Ihre Funktion beenden können, wenn die Variable Null ist:
Guard-Anweisungen wurden in Swift 2 hinzugefügt. Mit Guard können Sie den "goldenen Pfad" durch Ihren Code beibehalten und immer mehr verschachtelte ifs vermeiden, die manchmal aus der Verwendung der optionalen Bindung "if let" resultieren.
Es gibt auch ein Konstrukt, das als "Null-Koaleszenz-Operator" bezeichnet wird. Es hat die Form "optional_var ?? replace_val". Es gibt eine nicht optionale Variable mit demselben Typ wie die im optionalen Daten enthaltenen Daten zurück. Wenn das optionale Element nil enthält, wird der Wert des Ausdrucks nach dem "??" Symbol.
Sie könnten also folgenden Code verwenden:
Sie können auch die Fehlerbehandlung try / catch oder guard verwenden, aber im Allgemeinen ist eine der anderen oben genannten Techniken sauberer.
BEARBEITEN:
Ein anderes, etwas subtileres Problem mit Optionen ist "implizit ausgepackte Optionen". Wenn wir foo deklarieren, können wir sagen:
In diesem Fall ist foo immer noch optional, aber Sie müssen es nicht auspacken, um darauf zu verweisen. Das bedeutet, dass Sie jedes Mal, wenn Sie versuchen, auf foo zu verweisen, abstürzen, wenn es gleich Null ist.
Also dieser Code:
Wird beim Verweis auf die Eigenschaft "kapitalisiert" von foo abstürzen, obwohl wir foo nicht zwangsweise auspacken. Der Druck sieht gut aus, ist es aber nicht.
Daher möchten Sie mit implizit ausgepackten Optionen sehr vorsichtig sein. (und vielleicht sogar ganz vermeiden, bis Sie ein solides Verständnis für Optionen haben.)
Fazit: Wenn Sie Swift zum ersten Mal lernen, geben Sie das "!" Charakter ist nicht Teil der Sprache. Es wird dich wahrscheinlich in Schwierigkeiten bringen.
quelle
guard
Klauseln. Es gibt nichts, über dessen Verwendungif var
ein Konstrukt genauso gültig ist wieif let
. Es gibt nichts anwhere
Klauseln, was meiner Meinung nach erwähnenswert ist, wenn es um dasif let
Binden geht (es entfernt in vielen Fällen eine ganze Verschachtelungsebene). Es gibt nichts über optionale Verkettung.Da die obigen Antworten klar erklären, wie man sicher mit Optionals spielt. Ich werde versuchen zu erklären, was Optionals wirklich schnell sind.
Eine andere Möglichkeit, eine optionale Variable zu deklarieren, ist
var i : Optional<Int>
Und der optionale Typ ist nichts anderes als eine Aufzählung mit zwei Fällen, dh
Also, um unserer Variablen 'i' eine Null zuzuweisen. Wir können tun
var i = Optional<Int>.none
oder einen Wert zuweisen, wir werden einen Wert übergebenvar i = Optional<Int>.some(28)
Laut Swift ist 'Null' das Fehlen von Wert. Und um eine Instanz zu erstellen, die mit initialisiert wurde, müssen
nil
wir uns an ein Protokoll halten, das aufgerufen wird,ExpressibleByNilLiteral
und wenn Sie es erraten haben, wird davon abgeraten , nur anderen Typen zuOptionals
entsprechenExpressibleByNilLiteral
und diesen zu entsprechen.ExpressibleByNilLiteral
hat eine einzige Methode namens,init(nilLiteral:)
die ein Instace mit nil initialisiert. Normalerweise wird diese Methode nicht aufgerufen. Laut einer schnellen Dokumentation wird davon abgeraten, diesen Initialisierer direkt aufzurufen, wenn der Compiler ihn aufruft, wenn Sie einen optionalen Typ mitnil
Literal initialisieren .Sogar ich muss meinen Kopf um Optionals wickeln (kein Wortspiel beabsichtigt): D Happy Swfting All .
quelle
Zunächst sollten Sie wissen, was ein optionaler Wert ist. Weitere Informationen finden Sie in der Programmiersprache Swift .
Zweitens sollten Sie wissen, dass der optionale Wert zwei Status hat. Einer ist der volle Wert und der andere ist ein Nullwert. Bevor Sie einen optionalen Wert implementieren, sollten Sie überprüfen, um welchen Status es sich handelt.
Sie können
if let ...
oderguard let ... else
und so weiter verwenden.Wenn Sie den Variablenstatus vor Ihrer Implementierung nicht überprüfen möchten, können Sie ihn auch verwenden
var buildingName = buildingName ?? "buildingName"
.quelle
Ich hatte diesen Fehler einmal, als ich versuchte, meine Outlets-Werte aus der Methode zur Vorbereitung auf den Übergang wie folgt festzulegen:
Dann stellte ich fest, dass ich die Werte der Ziel-Controller-Ausgänge nicht einstellen kann, da der Controller noch nicht geladen oder initialisiert wurde.
Also habe ich es so gelöst:
Ziel-Controller:
Ich hoffe, diese Antwort hilft jedem da draußen mit dem gleichen Problem, bei dem ich festgestellt habe, dass die markierte Antwort eine großartige Ressource für das Verständnis der Optionen und ihrer Funktionsweise ist, aber das Problem selbst nicht direkt angesprochen hat.
quelle
updateView
den Ziel-Controller anrufen sollen ;)updateView
In diesem Fall ist es jedoch nicht erforderlich , das im Ziel-Controller aufzurufen, da ich diename
Variable verwende, um dasnameLabel.text
im zu setzenviewDidLoad
. Aber wenn wir viel einrichten würden, wäre es sicherlich besser, eine andere Funktion zu erstellen und sieviewDidLoad
stattdessen von dort aus aufzurufen .Grundsätzlich haben Sie versucht, einen Nullwert an Stellen zu verwenden, an denen Swift nur Nicht-Nullwerte zulässt, indem Sie dem Compiler mitgeteilt haben, dass er Ihnen vertrauen soll, dass dort niemals ein Nullwert vorhanden sein wird, sodass Ihre App kompiliert werden kann.
Es gibt verschiedene Szenarien, die zu dieser Art von schwerwiegenden Fehlern führen:
Zwangsauspacken:
Wenn
someVariable
Null ist, dann bekommen Sie einen Absturz. Durch ein Force-Unwrap haben Sie die Null-Check-Verantwortung vom Compiler auf Sie übertragen. Durch ein erzwungenes Unwrap garantieren Sie dem Compiler, dass Sie dort niemals Null-Werte haben. Und raten Sie mal, was passiert, wenn ein Nullwert irgendwie endetsomeVariable
?Lösung? Verwenden Sie die optionale Bindung (auch bekannt als if-let) und führen Sie dort die Variablenverarbeitung durch:
Zwangsabgüsse:
Hier weisen Sie den Compiler durch Force Casting an, sich keine Sorgen mehr zu machen, da Sie dort immer eine
Rectangle
Instanz haben. Und solange das so ist, müssen Sie sich keine Sorgen machen. Die Probleme beginnen, wenn Sie oder Ihre Kollegen aus dem Projekt anfangen, Nicht-Rechteck-Werte zu verteilen.Lösung? Verwenden Sie die optionale Bindung (auch bekannt als if-let) und führen Sie dort die Variablenverarbeitung durch:
Implizit ausgepackte Optionen. Angenommen, Sie haben die folgende Klassendefinition:
Wenn nun niemand die
name
Eigenschaft durcheinander bringt, indem er sie auf setztnil
, funktioniert sie wie erwartet, wird jedochUser
von einem JSON initialisiert, dem die fehltname
Schlüssel , wird beim Versuch, die Eigenschaft zu verwenden, der schwerwiegende Fehler angezeigt.Lösung? Verwenden Sie sie nicht :) Es sei denn, Sie sind zu 102% sicher, dass die Eigenschaft zum Zeitpunkt ihrer Verwendung immer einen Wert ungleich Null hat. In den meisten Fällen funktioniert die Konvertierung in eine optionale oder nicht optionale Version. Wenn Sie es nicht optional machen, hilft Ihnen der Compiler auch dabei, indem Sie den Codepfaden mitteilen, die Sie verpasst haben, und dieser Eigenschaft einen Wert geben
Nicht angeschlossene oder noch nicht angeschlossene Steckdosen. Dies ist ein besonderer Fall von Szenario 3. Grundsätzlich haben Sie eine XIB-geladene Klasse, die Sie verwenden möchten.
Wenn Sie nun die Verbindung zum Outlet über den XIB-Editor verpasst haben, stürzt die App ab, sobald Sie den Outlet verwenden möchten. Lösung? Stellen Sie sicher, dass alle Steckdosen angeschlossen sind. Oder verwenden Sie den
?
Operator :emailTextField?.text = "[email protected]"
. Oder deklarieren Sie den Ausgang als optional. In diesem Fall zwingt Sie der Compiler jedoch, den gesamten Code zu entpacken.Werte, die von Objective-C stammen und keine Annullierungsanmerkungen enthalten. Nehmen wir an, wir haben die folgende Objective-C-Klasse:
Wenn nun keine Annullierungsanmerkungen angegeben werden (entweder explizit oder über
NS_ASSUME_NONNULL_BEGIN
/NS_ASSUME_NONNULL_END
), wird diename
Eigenschaft in Swift as importiertString!
(eine IUO - implizit entpackt optional). Sobald ein schneller Code den Wert verwenden möchte, stürzt er ab, wenn er gleichname
Null ist.Lösung? Fügen Sie Ihrem Objective-C-Code Anmerkungen zur Nullbarkeit hinzu. Beachten Sie jedoch, dass der Objective-C-Compiler in Bezug auf die Nullfähigkeit etwas freizügig ist. Möglicherweise erhalten Sie keine Werte, selbst wenn Sie diese explizit als markiert haben
nonnull
.quelle
Dies ist eher ein wichtiger Kommentar und deshalb können implizit entpackte Optionen beim Debuggen von
nil
Werten täuschen .Denken Sie an den folgenden Code: Er wird ohne Fehler / Warnungen kompiliert:
Zur Laufzeit wird jedoch der folgende Fehler ausgegeben : Schwerwiegender Fehler: Beim Auspacken eines optionalen Werts wurde unerwartet Null gefunden
Kannst du mir sagen, welches Objekt ist
nil
?Das kannst du nicht!
Der vollständige Code wäre:
Kurz gesagt, wenn
var address : Address!
Sie verwenden, verbergen Sie die Möglichkeit, dass eine Variablenil
von anderen Lesern stammen kann. Und wenn es abstürzt, bist du wie "Was zum Teufel?! Meinaddress
ist nicht optional. Warum stürze ich dann ab?!.Daher ist es besser, als solches zu schreiben:
Können Sie mir jetzt sagen, welches Objekt es war
nil
?Diesmal wurde Ihnen der Code klarer gemacht. Sie können rationalisieren und denken, dass es wahrscheinlich der
address
Parameter ist, der gewaltsam ausgepackt wurde.Der vollständige Code wäre:
quelle
Die Fehler
EXC_BAD_INSTRUCTION
undfatal error: unexpectedly found nil while implicitly unwrapping an Optional value
erscheinen am häufigsten, wenn Sie ein Storyboard deklariert haben@IBOutlet
, aber nicht mit dem Storyboard verbunden sind .Sie sollten auch lernen, wie Optionals funktionieren, wie in anderen Antworten erwähnt, aber dies ist das einzige Mal, das mir am häufigsten erscheint.
quelle
@IBOutlet
Ursache dieses Fehlers nicht den schwerwiegenden Fehler haben: Unerwartet Null gefunden, während implizit eine optionale Wertversion des Fehlers entpackt wird?Wenn dieser Fehler in CollectionView auftritt, versuchen Sie, auch eine CustomCell-Datei und Custom xib zu erstellen.
Fügen Sie diesen Code in ViewDidLoad () bei mainVC hinzu.
quelle
Ich bin auf diesen Fehler gestoßen, als ich von einem Tabellenansichts-Controller zu einem Ansichts-Controller gewechselt bin, weil ich vergessen hatte, den benutzerdefinierten Klassennamen für den Ansichts-Controller im Haupt-Storyboard anzugeben.
Etwas Einfaches, das es wert ist, überprüft zu werden, ob alles andere in Ordnung aussieht
quelle