Начиная с бета-версии 8.3, огромное количество предупреждений: «Строковая интерполяция дает описание отладки для необязательного значения; вы хотели сделать это явным?» появился в моем коде.
Например, предупреждение появляется в следующей ситуации, когда параметры могут привести к нулю:
let msg = "*** Error \(options["taskDescription"]): cannot load \(sUrl) \(error)"
Как было разработано ранее, для меня (и для компилятора) было нормально, что дополнительные параметры должны быть интерполированы как 'nil'. Но компилятор передумал.
Компилятор предлагает добавить конструктор String со следующим описанием:
let msg = "*** Error \(String(describing: options["taskDescription"])): cannot load \(sUrl) \(error)"
Очевидно, что результаты явные, но, на мой взгляд, очень громоздкие. Есть ли лучший вариант? Мне нужно исправить все эти предупреждения или лучше дождаться следующей бета-версии?
swift
swift3
optional
string-interpolation
Стефан де Лука
источник
источник
Swift 3
сломал свой собственный,log
и я сделал ошибку, просто используяprint
вместо этого. Всегда нужно создавать свою собственную оболочку, иначе вы будете втянуты в эту «новую функцию».Ответы:
Это изменение было внесено в этот пул-реквест из-за того, что интерполяция
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
В Swift 5 с новой системой интерполяции строк, представленной SE-0228 , другой вариант - добавить пользовательскую
appendInterpolation
перегрузку для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
И, при желании, вы можете даже удалить метку аргумента, чтобы полностью отключить предупреждение внутри модуля (или в конкретном файле, если вы отметите его как
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
Хотя лично я предпочел бы сохранить ярлык аргумента.
источник
?? "nil"
отключение предупреждения, которое, казалось, было умеренно популярным, поэтому может появиться в другом предложении в ближайшем будущем. Я согласен с тем, что этот обходной путь далеко не идеален - лично я считаю довольно очевидным ожидать,Optional(...)
что он будет вставлен в строку для сильного необязательного параметра - это действительно был только случай IUO, который нуждался в этом предупреждении IMO. Но Swift постоянно развивается, так что все это может измениться позже. Но пока это то, что у нас есть.guard result == nil else { print("result was \(result as Optional)") return }
if let
? то естьif let result = result { print("result was \(result)"); return }
. Не все досрочные возвращения нужно делать с охраной.Два более простых способа решения этой проблемы.
Опция 1:
Первый - "принудительное разворачивание" значения, которое вы хотели бы вернуть, используя взрыв (!)
var someValue: Int? = 5 print(someValue!)
Выход:
5
Вариант 2:
Другой способ, который может быть лучшим - это «безопасно развернуть» значение, которое вы хотите вернуть.
var someValue: Int? = 5 if let newValue = someValue { print(newValue) }
Выход:
5
Рекомендую выбрать вариант 2.
Совет: по возможности избегайте принудительного развертывания (!), Так как мы не уверены, всегда ли у нас будет значение, которое нужно развернуть.
источник
кажется, что использование String (описание: необязательно) является самым простым.
значение по умолчанию ?? не имеет смысла для не-строк, например Int.
Если Int равен нулю, тогда вы хотите, чтобы журнал показывал «ноль», а не по умолчанию для другого 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 и получения большого количества предупреждающих сообщений я придумал следующее, которое больше похоже на исходное поведение вывода, легко добавляется, уменьшает многословность использования «Строка (описание :)» как в коде, так и в выводе. .
По сути, добавьте необязательное расширение, которое дает строку, описывающую предмет в необязательном, или просто "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"
Спасибо за помощь по следующей ссылке:
check-if-variable-is-an-optional-and-what-type-it-wraps
источник
a?.b?.c.orNil
.См. Исправление Оле Бегемана . Я люблю это. Он создает
???
оператор, который затем можно использовать следующим образом: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"
источник
Дважды щелкните желтый треугольник, отображаемый в строке, содержащей это предупреждение. Это покажет FixIt с двумя решениями.
Используйте,
String(describing:)
чтобы отключить это предупреждение:Используя это, он станет
String(describing:<Variable>)
Например. :
String(describing: employeeName)
Обеспечить ,
default value
чтобы избежать этого предупреждения:Используя это, он станет
(<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)) } }
источник