Compte tenu de ce qui suit dans Swift:
var optionalString: String?
let dict = NSDictionary()
Quelle est la différence pratique entre les deux énoncés suivants:
optionalString = dict.objectForKey("SomeKey") as? String
contre
optionalString = dict.objectForKey("SomeKey") as! String?
swift
optional
downcast
optional-variables
sdduursma
la source
la source
Réponses:
La différence pratique est la suivante:
optionalString
sera une variable de typeString?
. Si le type sous-jacent est autre chose qu'un,String
cela sera simplement assignénil
à l'option.Cela dit, je sais que cette chose est un
String?
. Cela entraînera égalementoptionalString
un typeString?
, mais il plantera si le type sous-jacent est autre chose.Le premier style est ensuite utilisé avec
if let
pour déballer en toute sécurité l'option:la source
as? Types
- signifie que le processus de coulée vers le bas est facultatif. Le processus peut réussir ou non (le système retournera nil si la conversion descendante échoue).as! Type?
- Ici, le processus de down casting devrait réussir (!
indique que). Le point d'interrogation de fin indique si le résultat final peut être nul ou non.Plus d'informations concernant "!" et "?"
Prenons 2 cas
Considérer:
Ici, nous ne savons pas si le résultat de la conversion descendante de la cellule avec l'identificateur "Cell" vers UITableViewCell est un succès ou non. En cas d'échec, il retourne nil (nous évitons donc les plantages ici). Ici, nous pouvons faire comme indiqué ci-dessous.
Alors rappelons-nous-en comme ceci - Si
?
cela signifie que nous ne savons pas si la valeur est nulle ou non (le point d'interrogation vient quand nous ne savons pas des choses).Comparez cela à:
Ici, nous disons au compilateur que la conversion descendante devrait réussir. En cas d'échec, le système plantera. Nous donnons donc
!
quand nous sommes sûrs que la valeur est non nulle.la source
Pour clarifier ce que vacawama a dit, voici un exemple ...
Swift 3.0:
Swift 2.0:
la source
intNil as! String? // ==nil
ne provoque pas de plantage !!! ???, comme facultatif <Int> .Aucun n'est différent de facultatif <String> .Aucunas?
àString
? Pourquoi ne pas le rabaisserString?
? Pourquoi ne pas baissésas!
àString
?Any
place deAnyObject
as
utilisé pour la projection ascendante et le moulage de type en type pontéas?
utilisé pour un casting sécurisé, retourne zéro en cas d'échecas!
utilisé pour forcer le casting, crash en cas d'échecRemarque:
as!
impossible de convertir le type brut en facultatifExemples:
Exemple
En ajoutant un ? immédiatement après le type de données, vous indiquez au compilateur que la variable peut contenir un nombre ou non. Soigné! Notez que cela n'a pas vraiment de sens de définir des constantes optionnelles - vous ne pouvez définir leur valeur qu'une seule fois et vous pourrez donc dire si leur valeur sera nulle ou non.
Quand devrions-nous utiliser "?" et quand "!"
disons que nous avons une application simple basée sur UIKit. nous avons du code dans notre contrôleur de vue et souhaitons y présenter un nouveau contrôleur de vue. et nous devons décider de pousser la nouvelle vue à l'écran à l'aide du contrôleur de navigation.
Comme nous le savons, chaque instance de ViewController possède un contrôleur de navigation de propriété. Si vous créez une application basée sur un contrôleur de navigation, cette propriété du contrôleur de vue principale de votre application est définie automatiquement et vous pouvez l'utiliser pour pousser ou afficher des contrôleurs de vue. Si vous utilisez un seul modèle de projet d'application, il n'y aura pas de contrôleur de navigation créé automatiquement pour vous, donc le contrôleur de vue par défaut de votre application n'aura rien stocké dans la propriété navigationController.
Je suis sûr que vous avez déjà deviné qu'il s'agit exactement d'un cas pour un type de données facultatif. Si vous cochez UIViewController, vous verrez que la propriété est définie comme:
Revenons donc à notre cas d'utilisation. Si vous savez avec certitude que votre contrôleur de vue aura toujours un contrôleur de navigation, vous pouvez continuer et forcer le déballage:
Lorsque vous mettez un! derrière le nom de la propriété, vous dites au compilateur que je me fiche que cette propriété soit facultative, je sais que lorsque ce code s'exécute, il y aura toujours un magasin de valeurs, alors traitez cette option comme un type de données normal. N'est-ce pas sympa? Que se passerait-il s'il n'y avait pas de contrôleur de navigation pour votre contrôleur de vue? Si vous suggérez qu'il y aura toujours une valeur stockée dans navigationController était faux? Votre application va planter. Simple et moche comme ça.
Et si vous n'êtes pas sûr qu'il y aura toujours un contrôleur de navigation? Ensuite, vous pouvez utiliser? à la place d'un !:
Qu'est-ce que c'est? derrière le nom de la propriété indique au compilateur que je ne sais pas si cette propriété contient nil ou une valeur, donc: si elle a une valeur, utilisez-la, et sinon considérez simplement l'expression entière comme nulle. Effectivement le? vous permet d'utiliser cette propriété juste au cas où il y aurait un contrôleur de navigation. Non s'il s'agit de chèques de toute nature ou de pièces moulées de toute sorte. Cette syntaxe est parfaite lorsque vous ne vous souciez pas de savoir si vous avez un contrôleur de navigation ou non, et que vous ne voulez faire quelque chose que s'il y en a.
Un grand merci à Fantageek
la source
Ce sont deux formes différentes de Downcasting dans Swift.
(
as?
) , qui est connue pour être la forme conditionnelle , renvoie une valeur facultative du type vers lequel vous essayez de réduire.(
as!
) , qui est connue pour être la forme forcée , tente le downcast et force le résultat en une seule action composée.Pour plus de détails, veuillez consulter la section Type Casting de la documentation Apple.
la source
Peut-être que cet exemple de code aidera quelqu'un à comprendre le principe:
la source
Le premier est un "cast conditionnel" (regardez sous "opérateurs de conversion de type" dans la documentation que j'ai liée) . Si le cast réussit, la valeur de l'expression est enveloppée dans un optionnel et renvoyée, sinon la valeur renvoyée est nil.
Le second signifie que optionalString peut être un objet chaîne ou qu'il peut être nul.
Plus d'informations dans cette question connexe .
la source
Il peut être plus facile de se souvenir du modèle de ces opérateurs dans Swift comme:
!
implique «cela pourrait piéger», tandis que?
indique «cela pourrait être nul».se référer à: https://developer.apple.com/swift/blog/?id=23
la source
Je suis novice en Swift et j'écris cet exemple en essayant d'expliquer ce que je comprends des «optionnels». Si je me trompe, veuillez me corriger.
Merci.
(1) :
obj.lastName = obj.lName as! String
contre
(2):
obj.lastName = obj.lName as? String
Ans: (1) Ici, le programmeur est sûr qu'il
“obj.lName”
contient un objet de type chaîne. Alors donnez simplement cette valeur à“obj.lastName”
.Maintenant, si le programmeur est correct, il
"obj.lName"
s'agit d'un objet de type chaîne, alors pas de problème. "obj.lastName" sera défini sur la même valeur.Mais si le programmeur se trompe, cela signifie qu'il
"obj.lName"
n'est pas un objet de type chaîne, c'est-à-dire qu'il contient un autre objet de type comme "NSNumber", etc. Puis CRASH (Run Time Error).(2) Le programmeur n'est pas sûr que
“obj.lName”
contient un objet de type chaîne ou tout autre objet de type. Définissez donc cette valeur sur“obj.lastName”
s'il s'agit de type chaîne.Maintenant, si le programmeur est correct, il
“obj.lName”
s'agit d'un objet de type chaîne, alors pas de problème.“obj.lastName”
sera mis à la même valeur.Mais si le programmeur se trompe, cela signifie que obj.lName n'est pas un objet de type chaîne, c'est-à-dire qu'il contient un autre type d'objet comme
"NSNumber"
etc. Ensuite“obj.lastName”
sera mis à la valeur nil. Donc, pas de crash (heureux :)la source