Как решить "Строковая интерполяция создает описание отладки для необязательного значения; вы хотели сделать это явным?" в бета-версии 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.
использование
String(describing:)
to silence this warning:Using this it will become
String(describing:<Variable>)
Например.:
String(describing: employeeName)
Обеспечить
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))
}
}