2017-02-14 48 views
1
let f:() -> Void = { } 

let array = ["a", 1, false, f] as [Any] 

if array[3] is AnyObject { 
    print(array[3]) 
} 

为什么元素为AnyObject计算为true,即使数组设置为存储Any?数组存储任何对象也是AnyObject类型

为什么函数作为AnyObject评估为true,即使按定义AnyObject只能是类?

作为另一个例子:

let f:() -> Bool = { return true } 
let ff = f as AnyObject 
(ff as() -> Bool)() 

这违背在API doc的AnyObject的定义,其中指出:

AnyObject可以用作具体类型为任何 的一个实例类,类类型或仅类的协议。

或官方Swift Programming Language Guide

•任何可以在所有代表任何类型的实例,包括功能 类型。

•AnyObject可以表示任何类类型的实例。

在上面的例子中,它看起来像函数可以表示为AnyObject。

SO中有其他地方的解释(正如@hamish所指出的那样),因为在内部使用SwiftValue类,任何东西都可以桥接到AnyObject。解释的逻辑似乎是有缺陷的/反向的,因为我们应该使实现符合语言定义,而不是其他方式,所以要么实现不正确,要么AnyObject和类型检查运算符的定义不正确?

+2

因为* everything *是可桥接的到Swift 3中的'AnyObject'。参见[AnyObject不能在Xcode8 beta6中工作?](http://stackoverflow.com/q/39033194/2976878) – Hamish

+1

为什么以及如何将函数桥接到AnyObject?那不会打破AnyObject的定义吗?即使可能,这种行为似乎也是错误的。 – Boon

+2

阅读链接的问答 - 直接与Obj-C不兼容的东西被装箱在Objc-C兼容框中_SwiftValue。推理原因是因为'id'现在被连接到Swift作为'Any',所以'Any'需要可桥接回'id'。 – Hamish

回答

1

首先,Swift编程语言指南不是ISO 9899定义C的语言规范。(即使给定了ISO标准,也不是每个编译器都以相同的方式实现C,甚至不是100%符合标准)如果你发现编译器和文档之间存在分歧,那么它就像编译器bug一样可能是文档错误。

尽管如此,我相信你已经掩盖了该规范的一个重要组成部分,你参考:

AnyObject也可以用作具体类型为桥梁,以一个Objective-一个类型的实例C类。 Swift桥中Objective-C中的许多值类型,如String和Int。

() -> Void相当于dispatch_block_t,这桥ObjC作为dispatch_object(见dispatch/object.hos/object.h):

/* 
* By default, dispatch objects are declared as Objective-C types when building 
* with an Objective-C compiler. This allows them to participate in ARC, in RR 
* management by the Blocks runtime and in leaks checking by the static 
* analyzer, and enables them to be added to Cocoa collections. 
* See <os/object.h> for details. 
*/ 
OS_OBJECT_DECL_CLASS(dispatch_object); 

所以这里没有惊喜,() -> Void可强制转换为AnyObject

在实践中,几乎什么现在可以缩小到AnyObject(再次,从来看,任何可以是NSValue可以是AnyObject语言规范点,尽管这不是它究竟是如何实现的)。但是,

AnyObject不同于AnyAny表现得像一个协议(尽管不是协议)。 AnyObject表现得像每个班级的超类(尽管实际上是一个协议)。

let b = true       // true 
let bany = true as Any    // true 
let banyobj = true as AnyObject  // 1 <=== (because it's NSNumber) 

MemoryLayout.size(ofValue: b)  // 1 (size of a bool) 
MemoryLayout.size(ofValue: bany)  // 32 (size of a protocol box) 
MemoryLayout.size(ofValue: banyobj) // 8 (size of a reference pointer) 

type(of: b)       // Bool.Type 
type(of: bany)      // Bool.Type 
type(of: banyobj)     // __NSCFBoolean.Type 

(尝试同样的事情{}看到封闭的处理方式。)

这是合理的打开对AnyObject文档的缺陷,包括更明确的解释,任何类型都可以转换成一个使用as AnyObject的引用类型,但这只是一个遗漏,而不是已经存在的矛盾。 (如果这是一个矛盾,或者你觉得它很混乱,那么正确的答案是打开一个缺陷来改善文档以匹配Swift,而不是Swift来匹配文档。)

+0

非常有见地,谢谢Rob! – Boon

相关问题