Angesichts der folgenden in Swift:
var optionalString: String?
let dict = NSDictionary()
Was ist der praktische Unterschied zwischen den folgenden zwei Aussagen:
optionalString = dict.objectForKey("SomeKey") as? String
vs.
optionalString = dict.objectForKey("SomeKey") as! String?
swift
optional
downcast
optional-variables
sdduursma
quelle
quelle
Antworten:
Der praktische Unterschied ist folgender:
optionalString
wird eine Variable vom Typ seinString?
. Wenn der zugrunde liegende Typ etwas anderes als ein ist, wirdString
dies harmlos nurnil
dem optionalen Typ zugewiesen .Das heißt, ich weiß , dass dieses Ding ein ist
String?
. Auch dies führt inoptionalString
der Art zu seinString?
, aber es wird abstürzen , wenn der zugrunde liegende Typ etwas anderes.Der erste Stil wird dann verwendet
if let
, um das optionale Element sicher auszupacken:quelle
as? Types
- bedeutet, dass der Down Casting-Prozess optional ist. Der Prozess kann erfolgreich sein oder nicht (das System gibt null zurück, wenn das Downcasting fehlschlägt). Auf keinen Fall stürzt es ab, wenn das Downcasting fehlschlägt.as! Type?
- Hier sollte der Downcasting-Prozess erfolgreich sein (!
zeigt dies an). Das abschließende Fragezeichen gibt an, ob das Endergebnis Null sein kann oder nicht.Weitere Infos zu "!" und "?"
Nehmen wir 2 Fälle
Erwägen:
Hier wissen wir nicht, ob das Ergebnis des Herunterwerfens einer Zelle mit der Kennung "Zelle" auf UITableViewCell erfolgreich ist oder nicht. Wenn dies nicht erfolgreich ist, wird null zurückgegeben (daher vermeiden wir hier einen Absturz). Hier können wir wie unten angegeben vorgehen.
Erinnern wir uns also daran - Wenn
?
es bedeutet, dass wir nicht sicher sind, ob der Wert Null ist oder nicht (Fragezeichen kommt, wenn wir nichts wissen).Vergleichen Sie das mit:
Hier sagen wir dem Compiler, dass Downcasting erfolgreich sein sollte. Wenn dies fehlschlägt, stürzt das System ab. Wir geben also,
!
wenn wir sicher sind, dass der Wert nicht Null ist.quelle
Um zu verdeutlichen, was Vacawama gesagt hat, hier ein Beispiel ...
Swift 3.0:
Swift 2.0:
quelle
intNil as! String? // ==nil
verursacht keinen Absturz !!! ???, da Optional <Int> .None unterscheidet sich von Optional <String> .Noneas?
zuString
? Warum lässt du es nicht niederString?
? Warum gehst du nicht niedergeschlagenas!
zuString
?Any
stattdessen verwendet werdenAnyObject
as
Wird für Upcasting und Typguss auf überbrückten Typ verwendetas?
Wird für sicheres Gießen verwendet. Wenn dies fehlschlägt, wird Null zurückgegebenas!
wird verwendet, um das Casting zu erzwingen, stürzt ab, wenn dies fehlschlägtHinweis:
as!
Der Rohtyp kann nicht in optional umgewandelt werdenBeispiele:
Beispiel
Durch Hinzufügen eines ? Unmittelbar nach dem Datentyp teilen Sie dem Compiler mit, dass die Variable möglicherweise eine Zahl enthält oder nicht. Ordentlich! Beachten Sie, dass es nicht wirklich sinnvoll ist, optionale Konstanten zu definieren. Sie können ihren Wert nur einmal festlegen und können daher sagen, ob ihr Wert Null ist oder nicht.
Wann sollten wir "?" und wann "!"
Nehmen wir an, wir haben eine UIKit-basierte einfache App. Wir haben Code in unserem View Controller und möchten einen neuen View Controller darüber präsentieren. und wir müssen uns entscheiden, die neue Ansicht mit dem Navigationscontroller auf dem Bildschirm anzuzeigen.
Wie wir wissen, verfügt jede ViewController-Instanz über einen Eigenschaftsnavigationscontroller. Wenn Sie eine auf Navigationscontrollern basierende App erstellen, wird diese Eigenschaft des Master View Controllers Ihrer App automatisch festgelegt und Sie können sie zum Push- oder Popup von View Controllern verwenden. Wenn Sie eine einzelne App-Projektvorlage verwenden, wird kein Navigations-Controller automatisch für Sie erstellt, sodass im Standard-Ansichts-Controller Ihrer App nichts in der Eigenschaft navigationController gespeichert ist.
Ich bin sicher, Sie haben bereits vermutet, dass dies genau der Fall für einen optionalen Datentyp ist. Wenn Sie UIViewController aktivieren, sehen Sie, dass die Eigenschaft wie folgt definiert ist:
Kehren wir also zu unserem Anwendungsfall zurück. Wenn Sie sicher sind, dass Ihr View Controller immer über einen Navigationscontroller verfügt, können Sie das Entpacken erzwingen:
Wenn Sie eine setzen! Hinter dem Eigenschaftsnamen teilen Sie dem Compiler mit, dass es mir egal ist, dass diese Eigenschaft optional ist. Ich weiß, dass bei der Ausführung dieses Codes immer ein Wertspeicher vorhanden ist. Behandeln Sie diese Option daher wie einen normalen Datentyp. Na ist das nicht schön Was würde jedoch passieren, wenn Ihr Ansichtscontroller keinen Navigationscontroller enthält? Wenn Sie vorschlagen, dass immer ein Wert in navigationController gespeichert wird, war das falsch? Ihre App wird abstürzen. So einfach und hässlich.
Wie wäre es, wenn Sie nicht sicher sind, ob es immer einen Navigationscontroller geben wird? Dann können Sie verwenden? anstelle einer !:
Was zum ? Hinter dem Eigenschaftsnamen steht, dass der Compiler weiß, ob diese Eigenschaft nil oder einen Wert enthält. Wenn sie also einen Wert hat, verwenden Sie ihn und betrachten Sie im Übrigen einfach den gesamten Ausdruck nil. Effektiv die? Mit dieser Eigenschaft können Sie diese Eigenschaft nur für den Fall verwenden, dass ein Navigationscontroller vorhanden ist. Nein, wenn Schecks jeglicher Art oder Gussteile jeglicher Art. Diese Syntax ist perfekt, wenn Sie sich nicht darum kümmern, ob Sie einen Navigationscontroller haben oder nicht, und nur dann etwas tun möchten, wenn es einen gibt.
Vielen Dank an Fantageek
quelle
Es sind zwei verschiedene Formen von Downcasting in Swift.
(
as?
) , von dem bekannt ist, dass es sich um das bedingte Formular handelt , gibt einen optionalen Wert des Typs zurück, auf den Sie einen Downcast durchführen möchten.(
as!
) , von dem bekannt ist, dass es sich um die erzwungene Form handelt , versucht den Downcast und packt das Ergebnis als einzelne zusammengesetzte Aktion aus.Weitere Informationen finden Sie im Abschnitt Type Casting in der Apple-Dokumentation.
quelle
Vielleicht hilft dieses Codebeispiel jemandem, das Prinzip zu verstehen:
quelle
Die erste ist eine "bedingte Umwandlung" (siehe "Typumwandlungsoperatoren" in der Dokumentation, die ich verlinkt habe). . Wenn die Umwandlung erfolgreich ist, wird der Wert des Ausdrucks in ein optionales Zeichen eingeschlossen und zurückgegeben, andernfalls ist der zurückgegebene Wert Null.
Der zweite bedeutet, dass optionalString ein Zeichenfolgenobjekt oder Null sein kann.
Weitere Informationen finden Sie in dieser verwandten Frage .
quelle
Es ist möglicherweise am einfachsten, sich das Muster für diese Operatoren in Swift zu merken, da:
!
impliziert, dass "dies möglicherweise eine Falle ist", während?
anzeigt, dass dies möglicherweise null ist.Siehe: https://developer.apple.com/swift/blog/?id=23
quelle
Ich bin ein Neuling in Swift und schreibe dieses Beispiel, um zu erklären, wie ich 'Optionals' verstehe. Wenn ich falsch liege, korrigiere mich bitte.
Vielen Dank.
(1):
obj.lastName = obj.lName as! String
vs.
(2):
obj.lastName = obj.lName as? String
Antwort: (1) Hier ist der Programmierer verdammt sicher, dass er ein
“obj.lName”
Objekt vom Typ String enthält. Geben Sie einfach diesen Wert an“obj.lastName”
.Wenn der Programmierer korrekt ist, bedeutet dies, dass es sich um ein
"obj.lName"
Objekt vom Typ Zeichenfolge handelt, ist dies kein Problem. "obj.lastName" wird auf den gleichen Wert gesetzt.Wenn der Programmierer jedoch falsch ist, bedeutet dies, dass
"obj.lName"
es sich nicht um ein Objekt vom Typ Zeichenfolge handelt, dh es enthält ein anderes Objekt vom Typ "NSNumber" usw. Dann CRASH (Run Time Error).(2) Der Programmierer ist sich nicht sicher, ob er ein
“obj.lName”
Objekt vom Typ Zeichenfolge oder ein anderes Objekt vom Typ enthält. Setzen Sie diesen Wert also auf,“obj.lastName”
wenn es sich um einen Zeichenfolgentyp handelt.Wenn der Programmierer korrekt ist, bedeutet dies, dass es sich um ein
“obj.lName”
Objekt vom Typ Zeichenfolge handelt, ist dies kein Problem.“obj.lastName”
wird auf den gleichen Wert gesetzt.Wenn der Programmierer jedoch falsch ist, bedeutet dies, dass obj.lName kein Objekt vom Typ Zeichenfolge ist, dh ein anderes Objekt vom Typ
"NSNumber"
usw. enthält . Dann“obj.lastName”
wird der Wert auf Null gesetzt. Also, kein Absturz (Happy :)quelle