Depuis la version bêta 8.3, zillions warnings "L'interpolation de chaîne produit une description de débogage pour une valeur facultative; vouliez-vous rendre cela explicite?" apparu dans mon code.
Par exemple, l'avertissement est apparu dans la situation suivante, où les options pouvaient conduire à zéro:
let msg = "*** Error \(options["taskDescription"]): cannot load \(sUrl) \(error)"
Comme précédemment conçu, il était normal pour moi (et le compilateur) d'interpoler les options comme «nil». Mais le compilateur a changé d'avis.
Ce que le compilateur suggère est d'ajouter un constructeur String avec la description suivante:
let msg = "*** Error \(String(describing: options["taskDescription"])): cannot load \(sUrl) \(error)"
Evidemment, les résultats sont explicites mais aussi très très encombrants à mon avis. Y a-t-il une meilleure option? Dois-je corriger tous ces avertissements ou mieux attendre la prochaine version bêta?
swift
swift3
optional
string-interpolation
Stéphane de Luca
la source
la source
Swift 3
brisé le mienlog
et j'ai fait une erreur en utilisant simplement à laprint
place. Devrait toujours créer votre propre wrapper sinon vous serez foutu par ce genre de "nouvelle fonctionnalité".Réponses:
Il s'agit d'un changement qui a été apporté à cette demande d'extraction en raison du fait que l'interpolation
Optional(...)
dans la chaîne résultante est souvent indésirable, et peut être particulièrement surprenante dans les cas avec des options implicitement non emballées . Vous pouvez voir la discussion complète de ce changement sur la liste de diffusion ici .Comme mentionné dans la discussion sur la demande d'extraction (bien que malheureusement pas par Xcode) - une façon légèrement plus agréable de faire taire l'avertissement que l'utilisation de
String(describing:)
consiste à ajouter un cast au type facultatif de tout ce que vous interpolez, par exemple:var i: Int? = 5 var d: Double? = nil print("description of i: \(i as Int?)") // description of i: Optional(5) print("description of d: \(d as Double?)") // description of d: nil
Ce qui peut également être généralisé à
as Optional
:print("description of i: \(i as Optional)") // description of i: Optional(5) print("description of d: \(d as Optional)") // description of d: nil
Dans Swift 5, avec le nouveau système d'interpolation de chaîne introduit par SE-0228 , une autre option consiste à ajouter une
appendInterpolation
surcharge personnalisée pourDefaultStringInterpolation
:extension DefaultStringInterpolation { mutating func appendInterpolation<T>(optional: T?) { appendInterpolation(String(describing: optional)) } } var i: Int? = 5 var d: Double? = nil print("description of i: \(optional: i)") // description of i: Optional(5) print("description of d: \(optional: d)") // description of d: nil
Et, si vous le souhaitez, vous pouvez même supprimer l'étiquette d'argument pour désactiver l'avertissement entièrement dans un module (ou dans un fichier particulier si vous le marquez comme
fileprivate
):extension DefaultStringInterpolation { mutating func appendInterpolation<T>(_ optional: T?) { appendInterpolation(String(describing: optional)) } } var i: Int? = 5 var d: Double? = nil print("description of i: \(i)") // description of i: Optional(5) print("description of d: \(d)") // description of d: nil
Bien que personnellement, je préfère garder l'étiquette d'argument.
la source
?? "nil"
faire taire l'avertissement, qui semblait être légèrement populaire, donc pourrait apparaître dans une autre proposition dans un proche avenir. Je suis d'accord que cette solution de contournement est loin d'être idéale - personnellement, je pense qu'il est plutôt évident de s'attendreOptional(...)
à être interpolé dans la chaîne pour un optionnel fort - ce n'était vraiment le cas des IUO qui avaient besoin de cet avertissement IMO. Mais Swift est en constante évolution, donc tout cela peut changer plus tard. Mais pour l'instant, c'est ce que nous avons.guard result == nil else { print("result was \(result as Optional)") return }
if let
? ieif let result = result { print("result was \(result)"); return }
. Tous les retours anticipés ne doivent pas être effectués avec des gardes.Deux moyens plus simples de traiter ce problème.
Option 1:
Le premier serait par "forcer le déballage" de la valeur que vous souhaitez renvoyer en utilisant un bang (!)
var someValue: Int? = 5 print(someValue!)
Production:
5
Option 2:
L'autre façon, qui pourrait être la meilleure, consiste à "déballer en toute sécurité" la valeur que vous souhaitez renvoyer.
var someValue: Int? = 5 if let newValue = someValue { print(newValue) }
Production:
5
Je recommanderais d'aller avec l'option 2.
Conseil: évitez le déballage forcé (!) Lorsque cela est possible car nous ne savons pas si nous aurons toujours la valeur à déballer.
la source
semble utiliser String (décrivant: facultatif) est le plus simple.
valeur par défaut ?? n'a aucun sens pour les non-chaînes, par exemple Int.
Si Int est nul, vous voulez que le journal affiche «nil» et non par défaut un autre Int, par exemple 0.
Quelques codes de jeux à tester:
var optionalString : String? = nil var optionalInt : Int? = nil var description_ = "" description_ = description_ + "optionalString: \(String(describing: optionalString))\r" description_ = description_ + " optionalInt: \(String(describing: optionalInt))\r" print(description_)
Production
optionalString: nil optionalInt: nil
la source
Après la mise à jour vers Xcode 8.3 et avoir reçu de nombreux messages d'avertissement, j'ai proposé ce qui suit qui ressemble plus au comportement de sortie d'origine, facile à ajouter, réduit la verbosité de l'utilisation de "String (décrivant :)" à la fois dans le code et la sortie .
Fondamentalement, ajoutez une extension facultative qui donne une chaîne décrivant la chose dans l'option facultative, ou simplement «nil» si elle n'est pas définie. De plus, si l'élément facultatif est une chaîne, mettez-le entre guillemets.
extension Optional { var orNil : String { if self == nil { return "nil" } if "\(Wrapped.self)" == "String" { return "\"\(self!)\"" } return "\(self!)" } }
Et utilisation dans une aire de jeux:
var s : String? var i : Int? var d : Double? var mixed = "s = \(s.orNil) i = \(i.orNil) d = \(d.orNil)" // "s = nil i = nil d = nil" d = 3 i = 5 s = "" mixed = "s = \(s.orNil) i = \(i.orNil) d = \(d.orNil)" // "s = "" i = 5 d = 3.0" s = "Test" d = nil mixed = "s = \(s.orNil) i = \(i.orNil) d = \(d.orNil)" // "s = "Test" i = 5 d = nil"
Merci pour l'aide du lien suivant:
vérifier-si-la-variable-est-une-option-et-quel-type-elle-enveloppe
la source
a?.b?.c.orNil
.Voir le correctif d'Ole Begeman pour cela . J'aime cela. Cela crée un
???
opérateur que vous pouvez ensuite utiliser comme ceci:var someValue: Int? = 5 print("The value is \(someValue ??? "unknown")") // → "The value is 5" someValue = nil print("The value is \(someValue ??? "unknown")") // → "The value is unknown"
la source
Double-cliquez sur le triangle jaune affiché sur la ligne contenant cet avertissement. Cela montrera FixIt avec deux solutions.
Utilisation
String(describing:)
pour faire taire cet avertissement:En utilisant cela, il deviendra
String(describing:<Variable>)
Par exemple. :
String(describing: employeeName)
Fournir un
default value
pour éviter cet avertissement:En utilisant cela, il deviendra
(<Variable> ?? default value)
Par exemple.:
employeeName ?? “Anonymous” as! String
la source
Swift 5
Ma solution consiste à créer un objet sur
extension
lequel déballer .Optional
Any
Lorsque vous connectez l'objet ou que vous l'imprimez, vous pouvez voir le
object
ou<nil>⭕️
(combinaison du texte et du caractère visuel). Il est utile de regarder, en particulier dans le journal de la console.extension Optional { var logable: Any { switch self { case .none: return "<nil>|⭕️" case let .some(value): return value } } } // sample var x: Int? print("Logging optional without warning: \(x.logable)") // → Logging optional without warning: <nil>|⭕️
la source
Créez une méthode d'interpolation qui accepte un type générique facultatif avec un paramètre sans nom. Tous vos avertissements ennuyeux disparaîtront comme par magie.
extension DefaultStringInterpolation { mutating func appendInterpolation<T>(_ optional: T?) { appendInterpolation(String(describing: optional)) } }
la source