我在类中有一个可能没有值的实例变量,所以它被定义为可选:
var myObject: MyClass?
在viewDidLoad()
方法中,我正在检查myObject
是否有值,如果是,则使用值。但是,Xcode会自动更正代码以使用?
来解包可选内容,而不是!
if myObject != nil {
print(myObject?.propertyOne)
print(myObject?.propertyTwo)
}
我很困惑为什么会这样,因为我认为你需要使用!
解包选项,而?
定义一个可选项。使问题更加混乱的是!
也可以工作:
if myObject != nil {
print(myObject!.propertyOne)
print(myObject!.propertyTwo)
}
感谢您的帮助。
答案 0 :(得分:3)
测试nil
的可选项与测试任何其他值的可选项不同。我认为这就是导致你混淆的原因。
E.g。如果您有myObject: MyClass?
,那么您可以
if myObject != nil {
// Still have to unwrap myObject to use it, cause it's still an optional.
// But at least you knowat this point that force unwrapping of myObject
// won't fail at runtime.
}
但你不能
if myObject != aNonNilValue {
}
- 你需要打开来做后者。
关于你的代码示例,使用Swift 2语法做同样事情的更现代的方法是:
if let myObject = myObject
{
// myObject is not an optional in this scope, so no unwrapping needed!
print(myObject.propertyOne)
print(myObject.propertyTwo)
}
else
{
print("oops, myObject is nil!")
}
起初看起来有点令人困惑。赋值左侧的myObject
是一个新变量,它保存原始myObject
的展开值。它不必具有与可选项相同的可选名称。 。如果原始myObject
为零,那么if let
将无法执行,而其下方的区块将无法运行。
使用上面的if let
方法可以帮助避免运行时错误,因为它可以避免潜在的危险力展开操作。
答案 1 :(得分:2)
您在
中使用问号的方式myObject?.propertyOne
称为可选链接。见Optional Chaining
如果propertyOne
不是myObject
,那么该表达式的值是nil
的值,否则它是nil
。 (我应该补充说,该表达式的类型为T?
,其中T
是propertyOne
的类型。)
!操作员是一个展开的力量。如果myObject
为零,它会导致程序崩溃。
来自文档:
尝试使用!访问不存在的可选值会触发运行时错误。在使用之前,请务必确保可选项包含非零值!强行解开它的价值。
你也可以使用let
来安全地打开你的选项,就像@ Macondo2Seattle指出的那样。