web-dev-qa-db-fra.com

Comment résoudre "Une interpolation de chaîne produit une description de débogage pour une valeur optionnelle; vouliez-vous rendre cela explicite?" dans Xcode 8.3 beta?

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?" est apparu dans mon code.

Par exemple, l'avertissement est apparu dans la situation suivante, où les options pourraient mener à néant:

let msg = "*** Error \(options["taskDescription"]): cannot load \(sUrl) \(error)"

Comme précédemment conçu, les options pour interpoler les options comme étant "nulles" étaient acceptables pour moi (et le compilateur). Mais le compilateur a changé d'avis.

Le compilateur suggère d’ajouter un constructeur String avec la description suivante:

let msg = "*** Error \(String(describing: options["taskDescription"])): cannot load \(sUrl) \(error)"

De toute évidence, les résultats sont explicites mais aussi très très lourds à mon avis. Y a-t-il une meilleure option? Dois-je résoudre tous les problèmes ou attendre mieux pour la prochaine version bêta?

Screenshot for description

73

Ceci est un changement qui a été effectué dans cette demande d'extraction car il est souvent indésirable d'interpoler Optional(...) dans la chaîne résultante, et peut être particulièrement surprenant dans les cas où implicitement optionnels non emballés . 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 avec Xcode) - un moyen légèrement plus agréable de faire taire l'avertissement que d'utiliser String(describing:) consiste à ajouter un transtypage au type optionnel de ce que vous interpolez. 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 aussi ê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înes introduit par SE-0228 , une autre option consiste à ajouter une surcharge personnalisée appendInterpolation pour DefaultStringInterpolation :

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 le libellé de l'argument pour désactiver l'avertissement dans un module (ou dans un fichier particulier si vous le marquez comme suit: 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

Personnellement, je préférerais conserver l'étiquette de l'argument.

96
Hamish

Deux manières plus faciles de traiter ce problème.

Option 1:

Le premier serait de "décompresser de force" la valeur que vous souhaitez renvoyer en utilisant un bang (!)

var someValue: Int? = 5
print(someValue!)

Sortie:

5

Option 2:

L'autre manière, qui pourrait être la meilleure, consiste à "en toute sécurité" la valeur que vous voulez renvoyer.

var someValue: Int? = 5

if let newValue = someValue {
    print(newValue)
}

Sortie:

5

Je recommanderais d'aller avec l'option 2.

Conseil: évitez autant que possible de dérouler (!) Car nous ne sommes pas sûrs d'avoir toujours la valeur à déballer.

22
Mo Iisa

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 indique 'nil' et non par défaut à un autre Int, par ex. 0.

Quelques codes de terrain de jeu à 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_)

Sortie

optionalString: nil
optionalInt: nil
16
brian.clear

Après la mise à jour vers Xcode 8.3 et la réception de nombreux messages d'avertissement, j'ai proposé ce qui suit, qui ressemble davantage au comportement de sortie d'origine, facile à ajouter, réduit la verbosité d'utiliser "String (description de :)" à la fois dans le code et dans la sortie. .

En gros, ajoutez une extension facultative qui donne une chaîne décrivant la chose dans l'option, 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 un terrain de jeu:

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 de lien suivant:

check-if-variable-is-optionnel-et-quel-type-it-wraps

13
anorskdev

Voir la solution de Ole Begeman pour cela . J'aime cela. Il 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"
11
dar512

Double-cliquez sur le triangle jaune affiché sur la ligne contenant cet avertissement. Cela montrera FixIt avec deux solutions.

Screenshot added

  1. Utilisez String(describing:) pour faire taire cet avertissement:

    En utilisant cela, il deviendra String(describing:<Variable>)

    Par exemple. : String(describing: employeeName)

  2. Fournissez un default value pour éviter cet avertissement:

    En utilisant cela, il deviendra (<Variable> ?? default value)

    Ex .: employeeName ?? “Anonymous” as! String

8
Jayprakash Dubey