强制解包可选项和隐式解包可选项之间的区别

29

起初我对强制解包和隐式解包非常困惑。现在,我通过自学获得了以下理解:

隐式解包可选项(Implicitly unwrapped Optionals)并没有可用的操作,但是有些内容被称为隐式解包可选项。隐式解包可选项和普通可选项都是可选项,区别在于访问隐式解包可选项时,您可以自信地知道底层有一个有效值,准备好供使用。普通可选项需要 if let 绑定强制解包 (!) 操作才能访问可选变量后面的可能值。

总结:

强制解包 是对普通可选类型的操作

隐式解包可选项可选项,通常用于类初始化,在使用时不需要感叹号传递值。

问题:

我的理解是否正确?如果我的理解不准确,我将非常感谢您纠正我。

谢谢


3
如果你将一个值声明为隐式解包类型,那么它等同于在每个使用场景对其进行强制解包。 - cpimhoff
@cpimhoff 这样可以节省你的时间,因为每次都不需要加感叹号。谢谢 ") - SLN
你可以观看这个视频,讲解得非常清晰 https://www.youtube.com/watch?v=BfWopYE2y4w - Dipesh Pokhrel
4个回答

92

首先让我们定义Optional

Optional值是某种类型(IntStringUIColor等)的容器,它可以包含值(1"Hello world".greenColor()等),也可以是 nil

let anOptionalInt: Int? = 1
let anotherOptionalInt: Int? = nil

图片描述

在Swift中,当我们看到一个Optional值时,我们会想:

好的,这个值可能包含实际值或者nil

强制解包

这是一种提取Optional内包含值的操作。 这个操作很危险,因为你在告诉编译器:我确定这个Optional值包含一个真实的值,请将其提取出来!

let anOptionalInt: Int? = 1
let anInt: Int = anOptionalInt!

现在,anInt 包含值 1。

输入图像描述

如果我们对包含nil的可选值进行强制解包,会导致fatalError,应用程序会崩溃并且无法恢复。

let anotherOptionalInt: Int? = nil
let anotherInt = anotherOptionalInt!

fatal error: unexpectedly found nil while unwrapping an Optional value

隐式解包可选项

当我们定义一个隐式解包可选项时,我们定义了一个容器,每次读取它时将自动进行强制解包。

输入图像描述

var text: String! = "Hello"

如果现在我们阅读 text

let name = text

我们得到的不是Optional String,而是普通的String,因为text自动解包了它的内容。

但是text仍然是一个可选值,所以我们可以在其中放置nil值。

text = nil

但是一旦我们读到它(它包含nil),我们就会遇到致命错误,因为我们正在展开一个包含nil的可选项。

let anotherName = text

fatal error: unexpectedly found nil while unwrapping an Optional value

4
非常感谢您提供如此详细的解释。 - SLN
2
感谢您的努力。 - Vinoth Vino
3
很好的解释,我只想指出强制解包本身并不危险,只有当你处理可能为空且超出你控制范围的数据时才会很危险。另一方面,如果你谈论的只是一个函数将某些局部作用域数据传递给另一个你编写的函数,那么在第二个函数中使用强制解包仍然可能产生错误,但这种错误是“好”的错误,它告诉你代码存在漏洞(因为你可能传递了错误的参数)。 - Andy
很好的解释。 - spnkr

5
一个隐式解包的可选项在幕后是一个普通的可选项,但也可以像非可选项值一样使用,所以你是正确的。
但如果您将一个值声明为隐式解包,则相当于在每次使用时强制解包它。
对于隐式解包的可选项,有四个主要原因。
1: 无法在初始化期间定义的常量
2:与Objective-C API交互
3: 当应用程序无法恢复变量为nil时
4: NSObject初始化器

感谢您的帮助和解释。 - SLN
1
2阶段初始化,特别是在UIViewController中。我不理解你关于NSObject的最后一点。 - Sulthan

2
我认为不是这样,你在做一个错误的区分:
  • 前半部分是正确的;解包肯定是针对Optionals进行的操作,并且强制解包是一种方法(不安全的方法)。

  • 但是关于什么是隐式解包的Optional:它是一种标记Optional类型的方式,因此如果您在无法使用Optional但可以解包的地方使用它,则会自动进行强制解包。


因此,这是一种创建独特可选项的方式/风格,它并不会创建新的概念可选项,它仍然是一个可选项,但具有额外的属性。 - SLN
2
以前有一个明确的类型ImplicitlyUnwrappedOptional,但现在它只是一个带有自动强制解包功能的Optional。 - matt

0

隐式解包

当您像这样定义其类型时,您可以将Optional定义为隐式解包。

let unwrappedString: String!

这种技术允许您告诉编译器自动解包该值,就好像它根本不是可选的一样。 与Type?类似,它是Optional的语法糖,Type!等同于ImplicitlyUnwrappedOptional。 隐式解包可选项的常见示例是视图控制器如何定义其IBOutlets:

@IBOutlet var displayLabel: UILabel! @IBOutlet var actionButton: UIButton!

将输出定义为隐式解包可选项是有意义的,因为它们将由Interface Builder实例化。在视图控制器中始终解包每个视图输出将很麻烦。 由于它们的隐式解包性质,如果您忘记将一个输出连接到Interface Builder视图并运行应用程序,则在尝试在视图控制器中访问它时会出现运行时错误。


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