强制展开可选的优点是什么?

What is the advantage of force unwrapping an optional?

如果变量是 Optional 强制展开它的优势是什么。

class Button: UIButton {
    var title: UILabel? = nil
    required init?(coder aDecoder: NSCoder) {
        fatalError()
    }

    override init(frame: CGRect) {
        super.init(frame: frame)
    }

    func addTitle(text: String) {
        title = UILabel(frame: CGRect())
        self.addSubview(title!)
    }

}

let a: Button = Button(frame: CGRect())
a.addTitle("Hello World")

// Case 1
a.title?.text = "Goodbye"

// Case 2
a.title!.text = "Hello World"

问题

案例 1 我知道它更安全但是是否有任何性能改进或使用理由 案例2

所以,如果我们知道 案例 1 更安全,我们为什么还要使用 案例2?

根据评论,您的示例实际上无效。抛开这一点:强制展开意味着 "I work only with a concrete value; I want to fail immediately if I don't have one"。因此,通常最好继续执行具有 nil 值的那部分代码,然后在因果关系被大幅削弱后的某个时候遇到其他问题。

因此:它允许您明确谁负责保证值的存在。

一些替代方案(避免强制展开 !)。使用 a 的 non-nil 值以及当 a 包含 nil.

时尝试这些
var a: String? = nil
a = "Hello World"

// Case 1 : nil coalescing operator
print(a ?? "a has value nil, let's not unwrap it!")

// Case 2 : if-let clause
if let a = a {
    print(a)
}
else {
    print("a has value nil, let's not unwrap it!")
}

// Case 3 : guard-let-else clause
func foo(a: String?) {
    guard let a = a else {
        print("a has value nil, let's not unwrap it!")
        return
    }
    print(a)
}
foo(a)

Performance-wise 强制和可选 binding/chaining 之间可能存在非常小的差异,因为可选版本可能在某处有额外的 if

但是尽管如此,当谈到性能问题时,性能瓶颈来自代码的其他部分,例如 non-improved 循环,大量累积 NSNotification 在短时间内发送, UI 等不必要的重绘

因此最好保持安全,使用可选的 binding/casting/chaining 并专注于增加实际性能损失的代码部分。即使在您编写代码时该值保证为 non-nil,将来情况可能会发生变化,您会突然以您没有预料到的崩溃告终发生。

Swift 使处理可选值变得非常容易,无需编写大量样板代码,您应该利用这些功能。

使用隐式解包 Optional 或使用 !:

强制解包 Optional 的充分(或至少是合理的)理由
  • @IBOutlets:由于几个原因,这些通常被隐式解包。您不希望每次访问它们时都必须手动打开它们。但更重要的是,如果您的插座连接不正确,您想立即知道。
  • 您有意识地决定在值为 nil 时应用程序崩溃的其他情况。例如,如果您从情节提要中实例化一个视图控制器,并且需要它是 UIViewController 的特定子类 MyViewController 才能让您的应用程序正常运行,您可以强制使用return vc as! MyViewController。这样你马上就会发现不对劲。

老实说,就我所知,就是这样。只是我自己的方法,但我保留 ! 用于声明 @IBOutlets。否则,99.999% 的时间我在可选链接情况下使用 if letguard? 解包。还有其他方法可以知道该值为 nil。如果可选的解包失败,则向控制台打印一条消息,告诉您它失败了。对我来说,一条简短的描述性消息比崩溃和 unexpectedly found nil while unwrapping an optional value 错误更容易调试。如果我想让程序失败,我仍然可以使用 fatalError 和描述性消息:

guard let x = someOptional else { fatalError("someOptional is nil in awakeFromNib.") }

通过将 ! 保留 @IBOutlet 秒,每次我遇到其中一个 unexpectedly found nil while unwrapping an optional value 错误时,我都知道在哪里可以找到问题的根源。我在界面生成器中查看我的 @IBOutlet 连接。坚持该政策,并使用其他工具来识别其他 nil 不应该的值,对我有用。