Свифт 3 неправильная строка интерполяции с неявно развернутые опции
почему неявно развернутые опции не разворачиваются при использовании Строковой интерполяции в Swift 3?
пример: Запуск следующего кода на игровой площадке
var str: String!
str = "Hello"
print("The following should not be printed as an optional: (str)")
производит этот выход:
The following should not be printed as an optional: Optional("Hello")
конечно, я могу объединить строки с + оператор, но я использую строку интерполяции почти везде в моем приложении, которое теперь не работает больше из-за этого (ошибка?).
это даже ошибка или они намеренно изменили это поведение с помощью Swift 3?
1 ответ:
по состоянию на SE-0054,
ImplicitlyUnwrappedOptional<T>больше не является отдельным типом; есть толькоOptional<T>сейчас.объявления по-прежнему могут быть аннотированы как неявно развернутые опционные
T!, но это просто добавляет скрытый атрибут, чтобы сообщить компилятору, что их значение может быть принудительно развернуто в контекстах, которые требуют их развернутого типаT; их фактический тип сейчасT?.так что вы можете думать об этом объявление:
var str: String!как на самом деле выглядит примерно так:
@_implicitlyUnwrapped // this attribute name is fictitious var str: String?только компилятор видит это
@_implicitlyUnwrappedатрибут, но то, что он позволяет это неявное разворачиваниеstrзначение в контекстах, которые требуютString(его развернул тип):// `str` cannot be type-checked as a strong optional, so the compiler will implicitly // force unwrap it (causing a crash in this case) let x: String = str // We're accessing a member on the unwrapped type of `str`, so it'll also be implicitly // force unwrapped here print(str.count)но во всех остальных случаях, когда
strможно тип-проверить как сильное опционное, оно будет:// x is inferred to be a String? (because we really are assigning a String?) let x = str // str is implicitly coerced from String? to Any let y: Any = strи компилятор всегда будет предпочитать рассматривать его как таковой над силой развертка.
как говорится в предложении (Курсив мой):
если выражение может быть явно тип проверен с сильным необязательным типом, это будет. Однако при необходимости средство проверки типов вернется к принудительному принудительному использованию. Эффект такого поведения заключается в том, что результат любого выражения, которое ссылается на значение, объявленное как
T!либо будет иметь типTили типаT?.когда дело доходит до Строковой интерполяции, под капотом компилятор использует этот инициализатор из
_ExpressibleByStringInterpolationпротокол чтобы оценить сегмент интерполяции строки:/// Creates an instance containing the appropriate representation for the /// given value. /// /// Do not call this initializer directly. It is used by the compiler for /// each string interpolation segment when you use string interpolation. For /// example: /// /// let s = "\(5) x \(2) = \(5 * 2)" /// print(s) /// // Prints "5 x 2 = 10" /// /// This initializer is called five times when processing the string literal /// in the example above; once each for the following: the integer `5`, the /// string `" x "`, the integer `2`, the string `" = "`, and the result of /// the expression `5 * 2`. /// /// - Parameter expr: The expression to represent. init<T>(stringInterpolationSegment expr: T)поэтому при неявном вызове вашим кодом:
var str: String! str = "Hello" print("The following should not be printed as an optional: \(str)")как
strфактический тип -String?, по умолчанию это то, что компилятор будет выводить общий заполнительTбыть. Поэтому значениеstrне будет принудительно развернут, и вы в конечном итоге увидите описание для дополнительного.если вы хотите, чтобы IUO был принудительно развернут при использовании в интерполяции строк, вы можете просто использовать оператор force unwrap
!:var str: String! str = "Hello" print("The following should not be printed as an optional: \(str!)")или вы можете принудить к его необязательному типу (в этом случае
String) для того, чтобы заставить компилятор неявно развернуть его для вас:print("The following should not be printed as an optional: \(str as String)")оба из которых, конечно, рухнет, если
strisnil.