可选择打开包装?在斯威夫特

时间:2015-12-17 03:37:22

标签: swift optional

我在类中有一个可能没有值的实例变量,所以它被定义为可选:

var myObject: MyClass?

viewDidLoad()方法中,我正在检查myObject是否有值,如果是,则使用值。但是,Xcode会自动更正代码以使用?来解包可选内容,而不是!

if myObject != nil {
  print(myObject?.propertyOne)
  print(myObject?.propertyTwo)
}

我很困惑为什么会这样,因为我认为你需要使用!解包选项,而?定义一个可选项。使问题更加混乱的是!也可以工作:

if myObject != nil {
  print(myObject!.propertyOne)
  print(myObject!.propertyTwo)
}

感谢您的帮助。

2 个答案:

答案 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?,其中TpropertyOne的类型。)

!操作员是一个展开的力量。如果myObject为零,它会导致程序崩溃。 来自文档:

  

尝试使用!访问不存在的可选值会触发运行时错误。在使用之前,请务必确保可选项包含非零值!强行解开它的价值。

你也可以使用let来安全地打开你的选项,就像@ Macondo2Seattle指出的那样。