first - string init swift



Como resolver “A interpolação de string produz uma descrição de depuração para um valor opcional; você quis fazer isso explícito? ”no Xcode 8.3 beta? (4)

Clique duas vezes no triângulo amarelo exibido na linha que contém esse aviso. Isso mostrará o FixIt com duas soluções.

  1. Use String(describing:) para silenciar este aviso:

    Usando isso, ele se tornará String(describing:<Variable>)

    Por exemplo. : String(describing: employeeName)

  2. Forneça um default value para evitar esse aviso:

    Usando isso, ele se tornará (<Variable> ?? default value)

    Por exemplo: employeeName ?? “Anonymous” as! String employeeName ?? “Anonymous” as! String

Desde beta 8.3, zillions warnings "A interpolação de string produz uma descrição de depuração para um valor opcional; você quis dizer isso explícito?" apareceu no meu código.

Por exemplo, o aviso apareceu na seguinte situação, onde as opções podem levar a zero:

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

Como projetado anteriormente, foi ok para mim (e o compilador) os opcionais serem interpolados como 'nil'. Mas o compilador mudou de ideia.

O que o compilador sugere é adicionar um construtor String com a descrição da seguinte forma:

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

Obviamente, os resultados são explícitos, mas também muito complicados na minha opinião. Existe uma opção melhor? Eu tenho que consertar todos esses avisos ou esperar pelo próximo beta?


Depois de atualizar para o Xcode 8.3 e obter um monte de mensagens de aviso, eu vim com o seguinte que é mais como o comportamento de saída original, fácil de adicionar, reduz a verbosidade de usar "String (descrevendo :)" tanto em código e saída .

Basicamente, adicione uma extensão opcional que dá uma String descrevendo a coisa no opcional, ou simplesmente "nil" se não for definido. Além disso, se a coisa no opcional for uma String, coloque-a entre aspas.

extension Optional {
    var orNil : String {
        if self == nil {
            return "nil"
        }
        if "\(Wrapped.self)" == "String" {
            return "\"\(self!)\""
        }
        return "\(self!)"
    }
}

E uso em um playground:

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"

Obrigado pela ajuda do seguinte link:

check-if-variable-is-an-optional-and-what-type-it-wraps


Esta é uma mudança que foi feita neste pedido de pull devido ao fato de que a interpolação Optional(...) na string resultante é geralmente indesejável, e pode ser especialmente surpreendente em casos com opcionais implicitamente não-desembrulhados . Você pode ver a discussão completa dessa alteração na lista de discussão here .

Como mencionado na discussão de solicitação de pull (embora infelizmente não pelo Xcode) - uma maneira um pouco mais agradável de silenciar o aviso do que o uso de String(describing:) é adicionar uma conversão ao tipo opcional de qualquer coisa que você esteja interpolando. exemplo:

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

Que também pode ser generalizado 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

No Swift 5, com o novo sistema de interpolação de strings introduzido pelo SE-0228 , outra opção é adicionar uma sobrecarga personalizada de appendInterpolation para 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

E, se desejar, você pode até mesmo remover o rótulo do argumento para desativar o aviso inteiramente dentro de um módulo (ou dentro de um arquivo específico, se você o marcar como 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

Embora pessoalmente eu preferiria manter o rótulo do argumento.


parece usando String (descrevendo: opcional) é mais simples.

valor padrão ?? não faz sentido para não-cordas, por exemplo, Int.
Se Int for nil, você deseja que o log mostre 'nil' e não padrão para outro Int, por exemplo, 0.

Algum código de playground para testar:

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_)

Saída

optionalString: nil
optionalInt: nil




string-interpolation