Que par SOI-0054, ImplicitlyUnwrappedOptional<T>
n'est plus un type distinct; il n'est qu' Optional<T>
maintenant.
Les déclarations sont encore autorisés à être annoté comme implicitement déballé options T!
, mais cela ajoute un attribut caché à informer le compilateur que leur valeur peut être la force déballé dans des contextes qui exigent de leurs déballé type T
; leur type réel est maintenant T?
.
Ainsi, vous pouvez penser de cette déclaration:
var str: String!
effectivement ressembler à ceci:
@_implicitlyUnwrapped // this attribute name is fictitious
var str: String?
Seul le compilateur voit ce @_implicitlyUnwrapped
d'attribut, mais ce qu'il permet pour est implicite déballage de la str
s'valeur dans des contextes qui demande un String
(non déballé):
// `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)
Mais dans tous les autres cas où l' str
peut être cochée qu'une forte facultatif, ce sera:
// 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
Et le compilateur préférera toujours la considérer comme tel sur la force de déballage.
Comme la proposition dit (l'emphase est mienne):
Si l'expression peut être explicitement type vérifié avec une forte option type, il sera. Cependant, le type de vérificateur de tomber en arrière pour forcer l'option si nécessaire. L'effet de ce comportement est que le résultat d'une expression qui se réfère à une valeur déclarée T!
sera soit de type T
ou de type T?
.
Quand il s'agit de la chaîne d'interpolation, sous le capot, le compilateur utilise cette initialiser à partir de l' _ExpressibleByStringInterpolation
protocole pour évaluer une chaîne d'interpolation segment:
/// 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)
Par conséquent, lorsque implicitement appelé par votre code:
var str: String!
str = "Hello"
print("The following should not be printed as an optional: \(str)")
En tant que str
s'type réel est - String?
, par défaut qu'est ce que le compilateur déduit le générique de l'espace réservé T
. Par conséquent, la valeur de str
ne sera pas en vigueur déballé, et vous finirez par voir la description facultative.
Si vous le souhaitez pour un IUO de force déballé quand utilisé dans la chaîne de l'interpolation, vous pouvez simplement utiliser la force de déballer l'opérateur !
:
var str: String!
str = "Hello"
print("The following should not be printed as an optional: \(str!)")
ou vous pouvez forcer à sa non-type facultatif (dans ce cas - String
) afin de forcer le compilateur à implicitement force déballer pour vous:
print("The following should not be printed as an optional: \(str as String)")
tous deux, bien sûr, va planter si str
est nil
.