J'utilise Xcode 6 Beta 4. J'ai cette situation étrange où je ne peux pas comprendre comment tester de manière appropriée les options.
Si j’ai un xyz en option, c’est la bonne façon de tester:
if (xyz) // Do something
ou
if (xyz != nil) // Do something
Les documents disent de le faire de la première façon, mais j'ai constaté que parfois, la deuxième est nécessaire et ne génère pas d'erreur de compilateur, mais d'autres fois, la deuxième génère une erreur de compilateur.
Mon exemple spécifique utilise l’analyseur XML GData ponté vers Swift:
let xml = GDataXMLDocument(
XMLString: responseBody,
options: 0,
error: &xmlError);
if (xmlError != nil)
Ici, si je viens de le faire:
if xmlError
cela reviendrait toujours vrai. Cependant, si je le fais:
if (xmlError != nil)
alors cela fonctionne (comme cela fonctionne dans Objective-C).
Y at-il quelque chose avec le XML GData et la façon dont il traite les options que je manque?
Dans Xcode Beta 5, ils ne vous permettent plus de faire:
var xyz : NSString?
if xyz {
// Do something using `xyz`.
}
Cela produit une erreur:
n'est pas conforme au protocole 'BooleanType.Protocol'
Vous devez utiliser l'un de ces formulaires:
if xyz != nil {
// Do something using `xyz`.
}
if let xy = xyz {
// Do something using `xy`.
}
Pour ajouter aux autres réponses, au lieu d’affecter une variable de nom différent à l’intérieur d’une condition if
:
var a: Int? = 5
if let b = a {
// do something
}
vous pouvez réutiliser le même nom de variable comme ceci:
var a: Int? = 5
if let a = a {
// do something
}
Cela pourrait vous aider à éviter de manquer de noms de variables créatives ...
Cela tire parti de observation variable qui est pris en charge dans Swift.
L'une des manières les plus directes d'utiliser les options est la suivante:
En supposant que xyz
soit de type facultatif, comme Int?
par exemple.
if let possXYZ = xyz {
// do something with possXYZ (the unwrapped value of xyz)
} else {
// do something now that we know xyz is .None
}
De cette façon, vous pouvez tester si xyz
contient une valeur et si c'est le cas, travailler immédiatement avec cette valeur.
En ce qui concerne votre erreur de compilation, le type UInt8
n'est pas optionnel (notez non '?') Et ne peut donc pas être converti en nil
. Assurez-vous que la variable avec laquelle vous travaillez est une option avant de la traiter comme telle.
Swift 3.0, 4.
Il existe principalement deux méthodes de vérification facultatives pour zéro. Voici des exemples de comparaison entre eux
1. Si laissé
if let
est le moyen le plus simple de vérifier facultatif pour nil. D'autres conditions peuvent être ajoutées à cette vérification nulle, séparées par une virgule. La variable ne doit pas être nulle pour passer à la condition suivante. Si seule la vérification est requise, supprimez les conditions supplémentaires dans le code suivant.
En dehors de cela, si x
n'est pas nul, la fermeture de if sera exécutée et x_val
sera disponible à l'intérieur. Sinon, la fermeture de else est déclenchée.
if let x_val = x, x_val > 5 {
//x_val available on this scope
} else {
}
2. Garde laisser
guard let
peut faire la même chose. Son objectif principal est de le rendre logiquement plus raisonnable. C'est comme si on disait Assurez-vous que la variable n'est pas nulle, sinon arrêtez la fonction . guard let
peut également effectuer une vérification de condition supplémentaire sous la forme if let
.
Les différences sont que la valeur non enveloppée sera disponible sur la même portée que guard let
, comme indiqué dans le commentaire ci-dessous. Cela conduit également au point que, en fermeture, le programme doit quitter la portée actuelle, par return
, break
, etc.
guard let x_val = x, x_val > 5 else {
return
}
//x_val available on this scope
De Swift programmation guide
Si instructions et décompression forcée
Vous pouvez utiliser une instruction if pour savoir si un facultatif contient une valeur. Si un facultatif a une valeur, sa valeur est true; s'il n'a aucune valeur, il est évalué à false.
Donc, la meilleure façon de faire est
// Swift > 3
if xyz != nil {}
et si vous utilisez la xyz
dans l'instruction if.Than, vous pouvez décompresser xyz
l'instruction if dans la variable constante. Vous n'avez donc pas besoin de décompresser chaque emplacement dans l'instruction if où xyz
est utilisé.
if let yourConstant = xyz{
//use youtConstant you do not need to unwrap `xyz`
}
Cette convention est suggérée par Apple
et elle sera suivie par les développeurs.
Bien que vous deviez toujours explicitement comparer une valeur optionnelle avec nil
ou utiliser une liaison facultative pour extraire en plus sa valeur (c’est-à-dire que les options ne sont pas converties implicitement en valeurs booléennes), il convient de noter que Swift 2 a ajouté la valeur guard
statement pour éviter la pyramide de Doom lorsque vous utilisez plusieurs valeurs facultatives.
En d'autres termes, vos options incluent désormais la vérification explicite de nil
:
if xyz != nil {
// Do something with xyz
}
Reliure optionnelle:
if let xyz = xyz {
// Do something with xyz
// (Note that we can reuse the same variable name)
}
Et guard
instructions:
guard let xyz = xyz else {
// Handle failure and then exit this code block
// e.g. by calling return, break, continue, or throw
return
}
// Do something with xyz, which is now guaranteed to be non-nil
Notez comment une liaison facultative ordinaire peut entraîner une indentation plus grande lorsqu'il existe plusieurs valeurs facultatives:
if let abc = abc {
if let xyz = xyz {
// Do something with abc and xyz
}
}
Vous pouvez éviter cette imbrication avec les instructions guard
:
guard let abc = abc else {
// Handle failure and then exit this code block
return
}
guard let xyz = xyz else {
// Handle failure and then exit this code block
return
}
// Do something with abc and xyz
Au lieu de if
, l'opérateur ternaire peut s'avérer utile lorsque vous souhaitez obtenir une valeur en fonction du caractère nul ou non:
func f(x: String?) -> String {
return x == nil ? "empty" : "non-empty"
}
Une autre approche en plus des instructions if
ou guard
pour effectuer la liaison facultative consiste à étendre Optional
avec:
extension Optional {
func ifValue(_ valueHandler: (Wrapped) -> Void) {
switch self {
case .some(let wrapped): valueHandler(wrapped)
default: break
}
}
}
ifValue
reçoit une fermeture et l'appelle avec la valeur en tant qu'argument lorsque facultatif n'est pas nul. Il est utilisé de cette façon:
var helloString: String? = "Hello, World!"
helloString.ifValue {
print($0) // prints "Hello, World!"
}
helloString = nil
helloString.ifValue {
print($0) // This code never runs
}
Vous devriez probablement utiliser un if
ou guard
cependant car ce sont les approches les plus conventionnelles (donc les plus familières) utilisées par les programmeurs Swift.
Une option qui n'a pas été spécifiquement couverte consiste à utiliser la syntaxe de valeur ignorée de Swift:
if let _ = xyz {
// something that should only happen if xyz is not nil
}
J'aime ça depuis que vérifier nil
ne convient pas à une langue moderne comme Swift. Je pense que la raison pour laquelle il ne se sent pas à sa place est que nil
est fondamentalement une valeur sentinelle. Nous avons supprimé les sentinelles un peu partout dans la programmation moderne, donc nil
semble devoir aller aussi.
Maintenant vous pouvez faire dans Swift la chose suivante qui vous permet de retrouver un peu de l’objectif-c if nil else
if textfieldDate.text?.isEmpty ?? true {
}
var xyz : NSDictionary?
// case 1:
xyz = ["1":"one"]
// case 2: (empty dictionary)
xyz = NSDictionary()
// case 3: do nothing
if xyz { NSLog("xyz is not nil.") }
else { NSLog("xyz is nil.") }
Ce test a fonctionné comme prévu dans tous les cas. Par ailleurs, vous n'avez pas besoin des crochets ()
.
Si vous avez conditionnel et que vous souhaitez décompresser et comparer, que diriez-vous de tirer parti de l'évaluation en court-circuit de l'expression booléenne composée comme dans
if xyz != nil && xyz! == "some non-nil value" {
}
Certes, cela n'est pas aussi lisible que certains des autres postes suggérés, mais le travail est fait et un peu succinct par rapport aux autres solutions suggérées.
Extension du protocole Swift 5
Voici une approche utilisant une extension de protocole afin que vous puissiez facilement intégrer une vérification nil facultative:
public extension Optional {
var isNil: Bool {
guard case Optional.none = self else {
return false
}
return true
}
}
tilisation
var myValue: String?
if !myValue.isNil {
// do something
}
Aussi, vous pouvez utiliser Nil-Coalescing Operator
Le _
nil-coalescing operator
_ (_a ?? b
_) décompresse una
facultatif s'il contient la valeura
ou renvoiea
la valeur par défautb
sia
estnil
. L'expression a est toujours d'un type optionnel. L'expressionb
doit correspondre au type stocké dansa
.
_let value = nullableValue ?? defaultValue
_
Si nullableValue
est nil
, il attribue automatiquement une valeur à defaultValue