我有一堂课,我有一个这样的属性:
var residenceId: Int!
使用Xcode 10和Swift 4.2进行构建时,没有问题。但是,在安装Xcode 11 Beta并转换为Swift 5之后,我得到以下警告:
Implicitly unwrapped property 'residenceId' declared here
稍后在课堂上我也有这个功能:
func jsonDictionary() -> [String : Any] {
return ["residenceId": residenceId]
}
我在这里得到警告
Coercion of implicitly unwrappable value of type 'Int?' to 'Any' does not unwrap optional
我们不再允许使用隐式展开的可选吗?
编辑:
更多研究之后,我开始相信“在这里声明的未包装属性'residenceId'”实际上不是警告,而是一些信息(以灰色标签而不是通常的黄色显示)可以提供帮助我明白为什么我会收到第二次警告。
为了澄清,我的问题是我们是否不再能够使用'!'属性上的符号定义一个隐式解开的属性(仅在我们确定它不会为nil时才明显),以便以后避免显式解开该属性(从而简化代码)。
答案 0 :(得分:4)
从Swift 4开始,我们所知道的ImplicitlyUnwrappedOptional
或!
变成了Optional
。
检查:
let a: ImplicitlyUnwrappedOptional<Int> = 1
会吐出错误:
“ ImplicitlyUnwrappedOptional”已重命名为“ Optional”
因此,如果我们这样做:
let a: Int! = 1
print(type(of: a)) //will print "Optional<Int>"
它仍然是Optional<Int>
,但向编译器指示可以隐式解包。
隐式展开是声明的一部分。
...
将
!
视为?
的同义词,另外,它在声明上添加一个标志,让编译器知道声明的值可以隐式展开。
Ref:Reimplementation of Implicitly Unwrapped Optionals
如果您这样做:
let a: Int! = 1
let b: Any = a
print(type(of: b)) //prints "Optional<Int>"
它将给出以下警告:
表达式从'Int?'隐式强制。到“任何”
或根据Xcode 11
强制转换为'Int?'类型的隐式不可包装值设为“任何”不会解开可选
请注意,我们尝试从Any
中获取非可选的Int?
,这意味着我们基本上期待Int
,但只需指定Any
即可还也解开Optional
。
它将保持为Optional
,这就是该警告的含义。
要优雅地处理此警告,我们可以执行以下任一操作:
let a: Int! = 1
let b: Any? = a
type(of: b) //Optional<Any>.Type
let c: Any! = a
type(of: c) //Optional<Any>.Type
let d: Any = a!
type(of: d) //Int.Type
!
而不是?
对程序员有什么实际区别?
!
告诉编译器可以将其隐式解包,从而可以简化对可选链接的需求。
示例:
使用?
class A {
var n: Int? = 1
}
class B {
var a: A? = A()
}
let b: B? = B()
print(b?.a?.n)
/*
but the following won't compile as compiler
will not implicitly unwrap optionals
print(b.a.n)
*/
使用!
class A {
var n: Int! = 1
}
class B {
var a: A! = A()
}
let b: B! = B()
print(b.a.n) //compiler will implicitly unwrap `!` similar to print(b!.a!.n)
//also... you can still safely unwrap if you want
print(b?.a?.n)
b.a.n
和b?.a?.n
都将在末尾给出Optional<Int>
b
或a
为nil
,则b.a.n
将会崩溃,因为它隐式解开了b
和a
以到达{{ 1}}即n
Optional<Int>
而不是Int
,您可以执行Optional<Int>
,因此您可以:b.a.n!
获取print(residenceId!)
我希望我有道理