存储任何对象的数组也是AnyObject类型

时间:2017-02-14 20:37:42

标签: swift3 anyobject

let f: () -> Void = { }

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

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

为什么AnyObject的元素评估为true,即使数组设置为存储Any?

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

另一个例子:

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

这违反了API doc中AnyObject的定义,其中声明:

  

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

或官方Swift Programming Language Guide

  

•Any可以代表任何类型的实例,包括函数   类型。

     

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

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

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

1 个答案:

答案 0 :(得分:1)

首先,Swift编程语言指南不是ISO 9899定义C的语言规范。(即使给出了ISO标准,并非每个编译器都实现相同的C,甚至100%符合标准。如果您发现编译器和文档之间存在分歧,那么作为编译器错误的文档错误就很可能。

那就是说,我相信你已经掩盖了你引用的规范的一个重要部分:

  

AnyObject也可以用作桥接到Objective-C类的类型实例的具体类型。 Swift中的许多值类型桥接到Objective-C对应物,如String和Int。

() -> Void相当于dispatch_block_t,它与dispatch_object(见dispatch/object.hos/object.h)的ObjC相连:

/*
 * 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 {1}},即使这不完全是如何实现的。)

AnyObjectAny不同。 Any表现得像一个协议(尽管不是协议)。 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来匹配文档。)