AnyObject相当于Swift的基类, 其实在实际编程过程中, 很少会需要把一个对象声明成AnyObject, 而且这货也没啥方法, 有啥好讲的呢.

在我们的App中, AnyObject主要用在网络请求回来的数据上, 请求回来的数据要拿来初始化model, 这时候一般都是AnyObject类型. 那有什么问题呢? 看这段代码:

let x: AnyObject = UIView()
let y = x.stringValue                   // 1. 不报错, y的类型是String!
x.testabc                               // 2. 编译报错: value of type 'AnyObject' has no member 'testabc'
x.backgroundColor                       // 3. 编译报错: ambiguous use of 'backgroundColor'
x.setTitle?("", forSegmentAtIndex: 0)   // 4. 不报错
x.setTitle("", forSegmentAtIndex: 0)    // 5. 运行时报错: unrecognized selector

为什么1, 4不报错, 2, 3, 5报错呢?

我们来看一下苹果官方对AnyObject的说明:

The protocol to which all classes implicitly conform. When used as a concrete type, all known @objc methods and properties are available, as implicitly-unwrapped-optional methods and properties respectively, on each instance of AnyObject.

所有的类实际上都是实现了这个protocol, 当一个变量声明成AnyObject的时候, 那么所有可以被这个变量访问的类中, 被标记为@objc的方法和被标记为@objc的属性对这个变量都是可见的, 而且是隐式解包的optional类型, 也就是!.

这样就可以解释上述代码中的问题了:

  • 1stringValueNSNumber的property, x.stringValue的返回值类型是String!, 因为对于AnyObject来讲, stringValue是隐式解包的optional. 如果x的实际类型是NSNumber的话, 返回值是正常的String!; 其它情况下, 返回值是nil
  • 2中的testabc并不是AnyObject的子类中@objc的属性, 编译的时候找不到.
  • 3中的backgroundColor虽然是@objc的属性, 但是因为在UIView和CALayer上都有定义, 编译器不知道用哪个.
  • 4采用了optional chain的调用方式, 如果方法不存在, 直接返回nil, 不会报错.
  • 5是直接调用该方法, 但是运行时, 系统查询UIView并没有这个方法, 抛出异常