AnyObject的返回值如何!与AnyObject不同

时间:2014-06-05 13:05:11

标签: swift forced-unwrapping

Swift下Cocoa框架中的NSMetadataItem类包含以下函数:

func valueForAttribute(key: String!) -> AnyObject!

我还在学习强制解包和可选链接之间的区别(和细节)。在上面的函数中,这是否意味着:

  1. key参数必须包含值,

  2. 保证返回值具有值?

  3. 我主要关注的是返回值后面的感叹号 - 一旦我分配了返回值:

    var isDownloadedVal = item.valueForAttribute(NSMetadataUbiquitousItemIsDownloadedKey)
    

    我在检查时是否需要包含if let块,或者我保证它会有一个我可以安全检查的值吗?

2 个答案:

答案 0 :(得分:19)

TLDR:将Foo!视为Foo

许多Cocoa调用包括隐式解包的选项,并且它们对它的需求很可能是该特征存在的原因。以下是我的建议。

首先,让我们考虑一个不涉及AnyObject的简单案例。我认为UIDevice是一个很好的例子。

class func currentDevice() -> UIDevice!

这里发生了什么?好吧,总有currentDevice。如果返回nil,则表明系统中存在某种深度错误。因此,如果我们在Swift中构建此接口,则可能只返回UIDevice并完成它。但我们需要桥接到Objective-C,它返回UIDevice*。现在不应该是nil,但语法上可以nil。现在在ObjC中,我们通常会忽略这一事实并且不要nil - 请在此处查看(特别是因为nil - 消息传递通常是安全的。)

那么我们如何在Swift中表达这种情况呢?嗯,从技术上来说它是一个Optional<UIDevice>,你最终得到了:

class func currentDevice() -> UIDevice?

并且您每次使用它时都需要明确地解开它(理想情况下使用if let块)。这很快会让你疯狂,无所事事。 currentDevice()始终返回一个值。 Optional是与ObjC桥接的工件。

所以他们发明了一个黑客来解决这个问题(我认为这真的是一个黑客;如果ObjC不在混合中,我无法设想构建这个功能)。那个黑客说,是的,它是一个Optional,但你可以假装它不是,我们保证它永远是一个价值。

那是!。对于这种类型的东西,你基本上忽略!并假装它将你送回UIDevice并滚动。如果他们骗你并返回nil,那么,那将会崩溃。他们不应该骗你。

这表明一条规则:除非你真的需要,否则不要使用!(而且你几乎只需要在与ObjC建立联系时)。

在您的具体示例中,这适用于两个方向:

func valueForAttribute(key: String!) -> AnyObject!

从技术上讲,它需要Optional<String>,但仅限于它与NSString*的桥接。您必须在此处传递非nil。从技术上讲,它会返回Optional<AnyObject>,但仅限于它与id的桥接。它承诺它不会成为nil

答案 1 :(得分:1)

根据Swift-eBook,其中陈述以下内容

“正在尝试使用!访问不存在的可选值会触发运行时错误。在使用之前,请务必确保可选项包含非零值!强行解开它的价值。“

我会用回答你的前两个问题。

  

检查时是否需要包含if let块?

,这不是必需的。