Swift 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?

    Согласно SE-0054 , ImplicitlyUnwrappedOptional больше не является отдельным типом; теперь есть только Optional .

    Объявлениям по-прежнему разрешено аннотироваться как неявно развернутые опции 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(stringInterpolationSegment expr: T) 

    Поэтому при неявном вызове вашего кода:

     var str: String! str = "Hello" print("The following should not be printed as an optional: \(str)") 

    Как фактический тип str является String? , по умолчанию это то, что компилятор будет вызывать общий заполнитель T Поэтому значение str не будет принудительно развернуто, и вы получите описание для необязательного.

    Если вы хотите, чтобы IUO был отключен от силы при использовании в строчной интерполяции, вы можете просто использовать оператор разворота силы ! :

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

    оба из которых, конечно же, будут разбиваться, если str равна nil .

    Interesting Posts

    Поддерживает ли OpenID Connect учетные данные пароля владельца ресурса?

    Поймите, как этот M.2 B + M Key SSD может работать через плату адаптера PCIe с 2 слотами (как 1 B, так и 1 М)?

    Нажмите кнопку переключения с помощью jQuery

    Как выбрать диапазон значений в инструкции switch?

    Notepad ++ как скопировать текст (только), который соответствует выражению регулярного выражения (не всей строки)

    Windows 8.1: на этот диск нельзя установить Windows

    Использование IEnumerable без цикла foreach

    Приоритет оператора (побитовый ‘&’ ниже, чем ‘==’)

    Модуль выгрузки Powershell … полностью

    NoClassDefFoundError для кода в библиотеке Java на Android

    Восстановление данных с диска NTFS после операции зеркального отображения RAID1

    Эмулировать цветовую палитру по умолчанию ggplot2

    Правильный способ закрыть вложенные streamи и записи в Java

    Восстановить миниатюры .psd в Windows 10, удалив ассоциацию файлов по умолчанию в реестре

    Bluetooth и WIFI для Android

    Давайте будем гением компьютера.