如果变量是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 ?
答案 0 :(得分:3)
根据评论,您的示例实际上并不有效。把它放在一边:强行展开意味着“我只用一个具体的价值工作;如果我没有,我想立即失败”。因此,通常优先使用nil
值继续执行该部分代码,然后在因果关系遭到严重侵蚀后再遇到其他问题。
所以:它允许你明确谁有责任保证价值存在。
答案 1 :(得分:3)
在性能方面,强制和可选绑定/链接之间可能存在非常非常小的差别,因为可选版本可能在某处有额外的if
。
但是在讨论性能问题时,性能瓶颈来自代码的其他部分,例如非改进的循环,在很短的时间内发送的大量累积NSNotification
,不必要的重绘用户界面等
因此,最好保持更安全的一面并使用可选的绑定/强制转换/链接,并专注于代码中增加实际性能损失的部分。即使在您编写代码时,该值仍保证为non-nil
,将来可能会出现条件发生变化,并且您最终会遇到崩溃但您没想到它们会发生故障。发生。
Swift已经很容易处理选项,没有编写很多样板代码,你应该利用这些功能。
答案 2 :(得分:2)
使用隐式解包的Optional
或使用Optional
强行展开!
的好(或至少是可防御的)原因:
@IBOutlet
s:由于几个原因,这些通常是隐式展开的。您不希望每次访问它们时都必须手动解包它们。但更重要的是,如果您的网点没有正确连接,您想立即知道。nil
,您有意识地决定要让应用崩溃的其他情况。例如,如果要从故事板中实例化视图控制器,并且需要成为UIViewController
的特定子类MyViewController
才能使您的应用程序正常运行,则可能强制使用它return vc as! MyViewController
。这样你就可以马上发现有些东西已经关闭。老实说,就我所知,就是这样。只是我自己的方法,但我保留!
来声明@IBOutlet
s。否则,99.999%的时间在可选链接情况下用if let
或guard
或?
打开。还有其他方法可以知道值为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
不应该使用的其他值,对我有用。
答案 3 :(得分: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)