암시 적으로 언 래핑 된 옵션으로 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<T>
더 이상 구별 유형; Optional<T>
지금 밖에 없습니다 .
선언은 여전히 묵시적으로 언 래핑 된 옵 셔널로 주석을 달 수 T!
있지만, 그렇게하면 컴파일러에게 그 값이 언 랩핑 된 타입을 요구하는 컨텍스트에서 강제로 언 래핑 될 수 있음을 알리기 위해 숨겨진 속성을 추가 할뿐입니다 T
. 그들의 실제 유형은 이제 T?
입니다.
따라서 다음 선언을 생각할 수 있습니다.
var str: String!
실제로 다음과 같이 보입니다.
@_implicitlyUnwrapped // this attribute name is fictitious
var str: String?
컴파일러 만이이 @_implicitlyUnwrapped
속성을 볼 수 있지만, 허용되는 것은 str
a 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
let y: Any = str // `str` is implicitly coerced from `String?` to `Any`
print(str) // Same as the previous example, as `print` takes an `Any` parameter.
그리고 컴파일러는 항상 강제 언 래핑보다 처리하는 것을 선호합니다.
제안에서 말했듯이 (내 강조) :
강력한 선택적 유형으로 표현식 을 명시 적으로 유형 검사 할 수있는 경우 . 그러나 유형 검사기는 필요한 경우 선택 사항을 강제로 다시 사용합니다. 이 동작의 효과는 선언 된 값을 참조하는 모든 표현식의 결과
T!
가 typeT
또는 type이라는 것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)")
As str
's actual type is String?
, by default that's what the compiler will infer the generic placeholder T
to be. Therefore the value of str
won't be force unwrapped, and you'll end up seeing the description for an optional.
If you wish for an IUO to be force unwrapped when used in string interpolation, you can simply use the force unwrap operator !
:
var str: String!
str = "Hello"
print("The following should not be printed as an optional: \(str!)")
or you can coerce to its non-optional type (in this case String
) in order to force the compiler to implicitly force unwrap it for you:
print("The following should not be printed as an optional: \(str as String)")
both of which, of course, will crash if str
is nil
.
'Program Tip' 카테고리의 다른 글
ggplot2 경고 설명 :“결 측값이 포함 된 k 개 행 제거됨” (0) | 2020.10.30 |
---|---|
해시 문자열 'android-22'로 대상을 찾지 못했습니다. (0) | 2020.10.30 |
이 파이썬 문자열의 크기가 실패한 int 변환에서 변경되는 이유 (0) | 2020.10.30 |
C # 코드에서 네이티브 예외를 포착 할 수 있습니까? (0) | 2020.10.30 |
backbone.js 뷰를 기존 요소에 첨부하는 것과 el을 DOM에 삽입하는 것 비교 (0) | 2020.10.30 |