Как решить "Строковая интерполяция создает описание отладки для необязательного значения; вы хотели сделать это явным?" в бета-версии Xcode 8.3?

Начиная с бета-версии 8.3, предупреждения zillions: "Строковая интерполяция создает описание отладки для необязательного значения; вы хотели сделать это явным?" появился в моем коде.

Например, предупреждение появилось в следующей ситуации, где опции могут привести к нулю:

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

Как и предполагалось ранее, для меня (и для компилятора) было вполне нормально, что опции должны быть интерполированы как 'nil'. Но компилятор передумал.

Компилятор предлагает добавить конструктор String с описанием следующим образом:

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

Очевидно, что результаты явные, но, на мой взгляд, очень громоздкие. Есть ли лучший вариант? Нужно ли исправлять все эти предупреждения или лучше подождать следующей беты?

Скриншот для описания

6 ответов

Решение

Это изменение, которое было сделано в этом запросе извлечения из-за того, что интерполяция Optional(...) в результирующую строку часто нежелательно и может быть особенно удивительно в случаях с неявно развернутыми опциями. Вы можете увидеть полное обсуждение этого изменения в списке рассылки здесь.

Как упомянуто в обсуждении запроса извлечения (хотя, к сожалению, не XCode) - один немного более хороший способ заставить замолчать предупреждение, чем использование String(describing:) это добавить приведение к необязательному типу того, что вы интерполируете, например:

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

Который также может быть обобщен на 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

Другой возможный способ заставить замолчать предупреждение - доступ Optional "s debugDescription:

print("description of i: \(i.debugDescription)") // description of i: Optional(5)
print("description of d: \(d.debugDescription)") // description of d: nil

Хотя стоит отметить, что документация для CustomDebugStringConvertible препятствует прямому доступу debugDescription,

Два более простых способа решения этой проблемы.

Опция 1:

Первым было бы "принудительное развертывание" значения, которое вы хотели бы вернуть, используя удар (!)

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

Выход:

5

Вариант 2:

Другой способ, который мог бы быть лучше, - это "безопасно развернуть" значение, которое вы хотите вернуть.

var someValue: Int? = 5

if let newValue = someValue {
    print(newValue)
}

Выход:

5

Рекомендую перейти с вариантом 2.

Совет: по возможности избегайте принудительного развертывания (!), Так как мы не уверены, что у нас всегда будет значение, которое необходимо развернуть.

Кажется, использование String(описание: необязательно) является самым простым.

значение по умолчанию?? не имеет смысла для не-строк, например, Int.
Если Int равен nil, то вы хотите, чтобы журнал показывал 'nil', а не значение по умолчанию для другого Int, например 0.

Какой-нибудь игровой код для тестирования:

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

Выход

optionalString: nil
optionalInt: nil

После обновления до Xcode 8.3 и получения большого количества предупреждающих сообщений, я пришел к следующему, которое больше похоже на исходное поведение вывода, легко добавляется, уменьшает многословность использования "String(descriptioning:)" как в коде, так и в выводе,

В основном, добавьте необязательное расширение, которое дает String, описывающий предмет в необязательном порядке, или просто "nil", если не установлено. Кроме того, если в необязательном элементе есть строка, поместите ее в кавычки.

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

И использование на детской площадке:

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"

Спасибо за помощь по следующей ссылке:

проверить, если переменной-это-ан-факультативный-и-пояски, что-типа

Смотрите исправление Оле Бегемана для этого. Я люблю это. Это создает ??? оператор, который вы затем можете использовать так:

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"

Double click on the yellow triangle displayed on line containing this warning. This will show FixIt with two solutions.

Добавлен скриншот

  1. использование String(describing:) to silence this warning:

    Using this it will become String(describing:<Variable>)

    Например.: String(describing: employeeName)

  2. Обеспечить default value to avoid this warning:

    Using this it will become (<Variable> ?? default value)

    Например.: employeeName ?? “Anonymous” as! String

Swift 5

Мое решение - сделать extension которые разворачивают Optional Возражать Any.

Когда вы регистрируете объект или распечатываете его, вы можете увидеть фактический object или <nil>⭕️(комбинация из текста и визуального символа). Полезно посмотреть, особенно в лог консоли.

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>|⭕️

Создайте метод интерполяции, который принимает необязательный универсальный тип с безымянным параметром. Все ваши надоедливые предупреждения волшебным образом исчезнут.

extension DefaultStringInterpolation {
  mutating func appendInterpolation<T>(_ optional: T?) {
    appendInterpolation(String(describing: optional))
  }
}
Другие вопросы по тегам