强制解包可选项的优点是什么?

3
如果一个变量是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


5
你的第一个案例不是有效的 Swift 代码,它无法编译。? 在可选链或可选下标中使用,因此应该跟随方法调用、属性查找或下标。 - Sebastian Osiński
我编辑了问题,使其更清晰并且可以编译。 - Cody Weaver
当你确定总是会有数据时,使用强制解包是很好的选择。这样可以避免在不必要的情况下使用 if-let 或 guard。 - Dan Beaulieu
4个回答

4
性能方面,强制绑定和可选绑定/链接可能会有非常小的差异,因为可选版本可能会在某个地方多出一个if语句。
但是,当谈到性能问题时,性能瓶颈来自代码的其他部分,例如未优化的循环、在短时间内发送大量的NSNotification、不必要的UI重绘等。
因此,最好保持安全并使用可选绑定/转换/链接,并专注于添加实际性能惩罚的代码部分。即使在编写代码时该值被保证为非零,将来条件可能会改变,您可能会突然遇到意料之外的崩溃。
Swift使处理可选项变得非常容易,而无需编写大量样板代码,您应该利用这些功能。

3
根据评论,你的例子实际上是无效的。抛开这个问题不谈: 强制解包意味着“我只使用一个具体值;如果没有一个值,我希望立即失败”。所以通常最好在代码部分中使用nil值之前强行终止,并在因果关系已经大幅削弱后的某个时候遇到其他问题。
因此:它允许您明确谁拥有保证值存在的责任。

我编辑了问题,使其更加清晰明了。 - Cody Weaver

2

使用隐式解包Optional或者强制解包Optional的好(或至少是可以辩护的)理由:

  • @IBOutlet:这些通常会被隐式解包,有几个原因。你不想每次访问它们时都手动解包。但更重要的是,如果你的outlets没有正确连接,你想立即知道。
  • 其他情况下,你做出了有意识的决定,如果一个值是nil,你希望应用程序崩溃。例如,如果你从storyboard实例化一个视图控制器,并且它需要是名为MyViewController的特定子类才能使你的应用程序正常运行,你可能会使用return vc as! MyViewController进行强制转换。这样你就可以立即发现有问题。

老实说,就我所知,就只有这些情况。这只是我的个人方法,但我保留!来声明@IBOutlet。否则,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的值,对我很有效。


1
一些替代方案(避免使用强制解包!)。尝试使用非空的a值以及当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)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接