Swift 斯威夫特';s在可为空性可用之前使用隐式展开可选

Swift 斯威夫特';s在可为空性可用之前使用隐式展开可选,swift,objective-c-nullability,Swift,Objective C Nullability,在苹果关于nullability的博客中,他们提到: “…在Swift中,可选和 非可选参考,例如NSView与NSView?,而Objective-C 将这两种类型都表示为NSView*。因为Swift 编译器无法确定特定NSView*是可选的还是可选的 否则,该类型将作为隐式展开的 可选,NSView!” 这是否意味着之前在Swift中将Objective-C方法声明为返回隐式展开可选时,它实际上可能会崩溃(因为某些使用隐式展开可选声明的方法可能返回nil)?或者苹果是否确保只有那些绝对不返

在苹果关于nullability的博客中,他们提到:

“…在Swift中,可选和 非可选参考,例如NSView与NSView?,而Objective-C 将这两种类型都表示为NSView*。因为Swift 编译器无法确定特定NSView*是可选的还是可选的 否则,该类型将作为隐式展开的 可选,NSView!”


这是否意味着之前在Swift中将Objective-C方法声明为返回隐式展开可选时,它实际上可能会崩溃(因为某些使用隐式展开可选声明的方法可能返回nil)?或者苹果是否确保只有那些绝对不返回nil的Objective-C方法被声明为隐式展开可选方法?

苹果的框架没有什么特别之处。一开始,您在Swift中从Objective-C使用的所有(每个对象)都是隐式展开的可选项。这是因为Objective-C中的每个指针都可能返回
nil

事实上,即使在Objective-C可空性注释的时代,注释为
nonnull
的方法返回
nil
也并非完全不可能。Objective-C并没有强制执行可空性规则,它只是提供了一种对代码进行注释的方法,以便在Swift中使用更安全。就苹果的框架而言,我敢打赌你不会有这个问题。或者,如果您这样做,下一版本的Xcode将修复它

但是,同样,来自Objective-C库和框架的隐式展开选项没有什么特别之处。隐式展开的可选项告诉您的唯一一件事是框架作者还没有努力注释他们的库(您不能将隐式展开的可选项保留在注释库中)是的,这些隐式展开的选项可以是
nil
,它们会使应用程序崩溃。

在苹果的例子中,如果出于某种原因,你在不同的项目上使用了Xcode 7和Xcode 6,如果你使用了Xcode 7的更新注释声明为非可选的东西,那么假设Xcode 6中隐式解包的可选版本永远不会是
nil
,这可能是可行的。但是如果你在Xcode 7中选择了一些可选的东西,假设Xcode 6的隐式解包版本永远不会是
nil
,那么你的应用程序很可能会崩溃

最终,在Swift中,我们对隐式展开选项的使用应该很少。隐式展开选项的主要用途应主要用于在类初始化返回之前无法设置的类属性(例如,视图控制器中的
@IBOutlets
)。否则,它们很容易成为关于堆栈溢出的大量“意外发现零”问题的来源


对于“为什么返回隐式展开的可选项而不是可选项?”的问题,有几点

首先,这是一个语言设计问题。我不是Objective-C或Swift语言设计团队的成员,这些团队中的任何人都不太可能过来回答这个问题

第二,这就是语言互操作的设计方式。任何未添加可空性注释的Objective-C文件都将被视为Swift中隐式展开的可选文件

第三,隐式optionals的原因是,它减少了optional所需的if letetc语句的大量冗余,同时不能保证变量实际上是
非nil
。大多数原因可能是因为您认为这些方法中的大多数实际上从未返回
nil

第四,如果你知道哪些人有机会成为
nil
,哪些人没有,你实际上可以继续写你的Swift代码,以一种既能处理对Objective-C代码的注释方式做出假设的方式

例如,对于隐式展开的可选项,您当然可以将其视为非可选项,并删除展开过程中涉及的一些次要细节

此外,对于隐式展开的可选项,如果您认为它可能是
nil
,那么所有可选的展开内容仍然可以使用它

例如:

override func someFunc(implicitVal: String!) -> String {
    return implicitVal ?? "It was nil!"
}

override func someOtherFunc(implicitVal: String!) -> String {
    return implicitVal
}
如果我们假设它们都是可选的,那么第二个例子就行不通了

如果我们假设它们是非可选的,那么第一个例子就行不通了

隐式展开选项允许Swift开发人员自由地将其视为,如果他们对值为
nil
的可能性做出正确的假设

这是否意味着之前将Objective-C方法声明为 在Swift中隐式返回unwrapped optional,实际上可能会崩溃 (因为有些方法声明为隐式展开可选) 可以返回零吗

不可以。隐式展开的optional是可选的,这意味着
nil
是完全可以接受的值。只有当您尝试在不使用可选绑定或可选链接的情况下直接访问其中的成员时,隐式展开可选的as
nil
不会崩溃

还是苹果只确保那些目标C 绝对不返回nil的方法被隐式声明为 未包装可选


如果已知它不返回
nil
,那么苹果在审计后会将其声明为非可选,而不是隐式展开的可选。只有在不知道它是否可以返回
nil
的情况下,它才会隐式地返回unwrapped optional。

Apple开始对objc框架进行注释,这样您就可以得到一个非可选的或可选的,他们正在减少impli的数量