1
let f: () -> Void = { }

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

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

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

即使 AnyObject 根据定义只能是类,为什么函数作为 AnyObject 的计算结果为 true?

再举一个例子:

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

这违反了API doc中 AnyObject 的定义,该定义指出:

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

或官方的Swift 编程语言指南

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

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

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

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

4

1 回答 1

1

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

也就是说,我相信您已经忽略了您引用的规范的一个重要部分:

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

() -> Void等价于,它作为一个(参见和)dispatch_block_t连接到 ObjC :dispatch_objectdispatch/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(同样,从语言规范的角度来看,任何可以是 an 的东西都NSValue可以是 an 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 以匹配文档。)

于 2017-02-15T13:40:02.853 回答