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

Cra*_*tis 3 swift forced-unwrapping

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

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

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

  1. key参数必须有一个值,

  2. 返回值保证有值吗?

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

var isDownloadedVal = item.valueForAttribute(NSMetadataUbiquitousItemIsDownloadedKey)
Run Code Online (Sandbox Code Playgroud)

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

Rob*_*ier 19

TLDR:Foo!好像是这样对待Foo.

许多Cocoa调用包括隐式解包的选项,并且它们对它的需求很可能是该特征存在的原因.以下是我推荐的思考方式.

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

class func currentDevice() -> UIDevice!
Run Code Online (Sandbox Code Playgroud)

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

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

class func currentDevice() -> UIDevice?
Run Code Online (Sandbox Code Playgroud)

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

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

那就是!.对于这种东西,你基本上忽略了!它并且假装它正在向你递回UIDevice并滚动.如果他们对你撒谎并返回nil,那么,那将会崩溃.他们不应该欺骗你.

这表明一个规则:!除非你真的需要,否则不要使用(而且你几乎只需要桥接到ObjC).

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

func valueForAttribute(key: String!) -> AnyObject!
Run Code Online (Sandbox Code Playgroud)

从技术上讲它需要一个Optional<String>,但只是因为它已经桥接NSString*.你必须nil在这里通过非.它在技术上会让你回归Optional<AnyObject>,但这只是因为它已经弥合了id.它承诺它不会nil.

  • ObjC-> Swift API转换几乎肯定是通过自动化工具(或自动化人员,也称为"实习生")完成的.我强烈怀疑他们仔细考虑了每个方法调用的语义.在这种情况下,`AnyObject?`会更有意义,你应该打开一个雷达(bugreport.apple.com)来请求它.可能任何采用NSErrorPointer的方法都应该返回? (3认同)
  • 【class func JSONObjectWithData(data:NSData!,options opt:NSJSONReadingOptions,error:NSErrorPointer) - > AnyObject!】我对这个NSJSONSerialization类函数有点困惑.使用无效的json时,它仍会返回nil,为什么不使用?但是! (2认同)