id 与 Swift 中的 AnyObject

Objetive-C 的开发者都知道其有一个类型 id,类似 C 中的 void*,是一个万精油的类型,可以指向任何对象。比如我们可以让一个 object 为 NSString:

id object = @“Hello, World!;

也可以指向其他东西:

object = @1024;

因为 id 是个对象,我们可以向它发消息:

[object lastObject];

在 Swift 中,有一个相应的 AnyObject 类型来表示任何类型:

var object: AnyObject = “Hello, World!”

object = 1024

object.lastObject()

但在实际使用中, id 与 AnyObject 又有少许区别,我们知道,在 Objective-C 中,对一个 id 对象发送消息,要格外小心,因为可能这个对象并不能响应这个消息,这样就会造成应用的崩溃。所以,一般我们会这样写:

if ([object respondsToSelector:@selector(lastObject)])
{
    [object lastObject];
}

而在 Swift 中,就可以写得简单点了。我们可以通过在 AnyObject 的方法的括号前面加问号的方式使其为「可空」的:

object.lastObject?()

Swift 会先看 object 是否能够响应 lastObject 消息,可以,则发送消息。不可以则返回 nil,什么也不做。

最后提的一点是向下转型,在 Objective-C 中,当我们知道某个 id 对象其实是一个特定类型时,我们可以很快的将它转型:

NSArray *array = object;

想当然的,我们以为在 Swift 中,这样就可以了:

let array:Array = object //error!

很遗憾,这样会报错。如果我们很确信 object 对象就是一个 Array 类型的对象,我们需要用 as 关键字显式地指出:

let array = object as Array

但如果我们并不十分确定呢?我们需要用 as? 关键字。与可空变量一样,其先尝试转型,如果成功,则返回 true,且转型。反之则返回 false:

if let array = object as? Array
{
    //现在可以用 array 了
}

Reference: WWDC 2014 Session 407

2014-06-07 11:541153