【问题标题】:Swift: Force Unwrapped returns nil without crashingSwift:Force Unwrapped 返回 nil 而不会崩溃
【发布时间】:2016-06-20 22:07:05
【问题描述】:

下面是我在操场上的代码:

let aNumber : NSNumber? = nil

func testFuction() -> NSNumber!{
    return aNumber
}

dump(testFuction())

输出:

- nil

我很困惑为什么它没有崩溃。返回值NSNumber! 显然为零,​​但它被强制解包。这不应该崩溃吗?请解释一下。

【问题讨论】:

  • 使用print 而不是dump,它会按预期崩溃。

标签: swift swift2 forced-unwrapping


【解决方案1】:

您正在返回一个隐式展开的可选 NSNumber!。返回的基础数据类型是可选的,但每次使用时都会自动解包。 Swift 包含这种类型,因此您不必在变量之后使用感叹号,您知道在某个点之后将是非 nil(例如,一个实例变量以 nil 开始,但在使用之前被初始化) .隐式展开的可选项允许包含 nil 值,但如果变量在实际尝试使用时为 nil,则会触发运行时错误,因为它在使用时被强制展开。

【讨论】:

  • 能否请您详细说明“每次使用它都会自动解包”。我的印象是func testFuction() -> NSNumber! 在返回值之前强行打开它?
  • @user1107173,要强制解包一个值,你需要在值后面加上感叹号,而不是在函数的返回类型后面。
  • 那么,函数返回值与函数签名中是否有一个点?
  • “每次你使用它都会自动解包”——假设你有var x: Int? = 5和var y: Int! = 5。然后print(x) 打印Optional(5) 而print(y) 打印5。所以x 没有被解包,并且是一个正常的可选,而y 在被打印之前被解包,所以只打印了5。 y 总是被假定为非零,因此在没有显式使用感叹号的情况下展开。 func testFuction() -> NSNumber! 返回一个隐式解包的 NSNumber 可选,但在您使用它之前不会对返回的值发生任何反应(如前面示例中的 y)。
  • 事实上,在实际使用中,返回一个隐式展开的可选项几乎没有任何意义;要么返回一个真可选,要么返回一个非可选并强制在函数体中解开返回值。返回隐式解包的可选项可能会使调试变得更加困难,因为在尝试使用返回值之前,您不会发现已将 nil 封装在隐式解包的可选项中。
【解决方案2】:

nilimplicitly-unwrapping optionals 在解包时会崩溃,并且将可选项传递给dump 不会解包它。当您将(隐式包装的)可选值(T!)作为未包装类型(T)的值传递时,会发生隐式展开,但如果函数接受可选值,则不会发生展开。

你可以通过像let unwrapped: NSNumber = testFunction() 这样的操作来进行隐式展开,这会崩溃。

如果您要强制解开值,感叹号会出现在值之后,而不是返回类型之后:

func testFuction() -> NSNumber {
    return aNumber!
}

【讨论】:

    【解决方案3】:

    你的函数返回一个隐式展开的可选。如果您尝试将其用作NSNumber,它将被隐式解包,但它仍然是可选的,因此它可以合法地具有nil 值。

    如果您在aNumber 后面加上一个感叹号并将其从函数返回类型中删除,您会如预期的那样崩溃:

    func testFuction() -> NSNumber {
        return aNumber!
    }
    

    【讨论】:

      猜你喜欢
      • 2017-11-21
      • 1970-01-01
      • 1970-01-01
      • 2019-05-08
      • 2015-09-08
      • 2018-12-08
      • 2011-03-31
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多