概念
- AnyObject:可以表示任何类类型的对象实例,所有类都隐式地遵循 AnyObject;
- Any:可以表示任何类型,包括基础数据类型、枚举类型、结构体、函数类型等;
- AnyClass:表示类的元类型,是AnyObject.Type的别名:定义typealias AnyClass = AnyObject.Type;
我们可以说AnyObject是Any的子集,Any和AnyObject都是Swift 的不确定的类型。
Any类型
- 类、结构体或者枚举;
- 元类型,比如 Int.self ;
- 带有任意类型元素的元组;
- 闭包或者函数类型。
let mixed: [Any] = ["one", 2, true, (4, 5.3), { () -> Int in return 6 }]
当你使用 Any 作为实例的具体类型时,你需要在访问其属性和方法之前把它转换成已知类型
if let first = mixed.first as? String {
print("The first item, '\(first)', is a string.")
}
// Prints "The first item, 'one', is a string."
AnyObject类型
所有类都隐式遵循AnyObject协议,这也限制了AnyObject是只适用于Class类型的原因。AnyObject与OC中的id
一样,它可以表示任意类的实例,译器不会对向声明为 id 的变量进行类型检查。因此,导入的OC类型经常使用AnyObject作为属性、方法参数和返回值的类型。
因为在Swift中的String,Array等类型都是struct类型定义的了,变成了值类型,与OC中的引用类型不同,并不能是AnyObject来表示。因此在混编时需要使用AnyObject类型将Swift的值类型来转化为OC的引用类型。
看下面的例子:
let s: AnyObject = "This is a bridged string." as NSString
print(s is NSString)
// Prints "true"
let v: AnyObject = 100 as NSNumber
print(type(of: v))
// Prints "__NSCFNumber"
再看一个例子
let swiftInt: Int? = 1
let swiftString: String = "miao"
var array: [AnyObject] = []
array.append(swiftInt as AnyObject) //Int,Array是结构体,任意类型用Any,所以类型不符合,要强转类型
array.append(swiftString as AnyObject)
我们在这里声明了一个 Int 和一个 String,按理说它们都应该只能被 Any 代表,而不能被 AnyObject 代表的。但是你会发现这段代码是可以编译运行通过的。那是不是说其实 Apple 的编程指南出错了呢?不是这样的,你可以打印一下 array,就会发现里面的元素其实已经变成了 NSNumber 和 NSString 了,这里发生了一个自动的转换。在 Swift 和 Cocoa 中的这几个对应的类型是可以进行自动转换的。因为我们显式地声明了需要 AnyObject,编译器认为我们需要的的是 Cocoa 类型而非原生类型,而帮我们进行了自动的转换。
AnyClass
所有类类型隐式遵守AnyClass协议
属于AnyObject.Type的别名:typealias AnyClass = AnyObject .Type
通过AnyObject.Type这种方式所得到的是一个元类型(Meta),声明时我们总是在类型的名称后面加上.Type,比如 A.Type 代表的是 A 这个类型的类型。也就是说,我们可以声明一个元类型来存储 A 这个类型本身,而在从 A 中取出其类型时,我们需要使用到 .self
class A {
class func method() {
print("Hello")
}
}
let typeA: A.Type = A.self
typeA,method()
或
let typeA: AnyClass = A.self
(typeA as! A.Type).method()
注:其实在 Swift 中,.self 可以用在类型后面取得类型本身,也可以用在某个实例后面取得这个实例本身。前一种方法可以用来获得一个表示该类型的值,这在某些时候会很有用;而后者因为拿到的实例本身,所以暂时似乎没有太多需要这么使用的案例。
使用示例1
class IntegerRef {
@objc class func getDefaultValue() -> Int {
return 42
}
}
func getDefaultValue(_ c: AnyClass) -> Int? {
return c.getDefaultValue?()
}
print(getDefaultValue(IntegerRef.self))
// Prints "Optional(42)"
print(getDefaultValue(NSString.self))
// Prints "nil"
使用示例2
class MusicViewController: UIViewController {
}
class AlbumViewController: UIViewController {
}
let usingVCTypes: [AnyClass] = [MusicViewController.self,
AlbumViewController.self]
func setupViewControllers(vcTypes: [AnyClass]) {
for vcType in vcTypes {
if vcType is UIViewController.Type {
let vc = (vcType as! UIViewController.Type).init()
print(vc)
}
}
}
setupViewControllers(usingVCTypes)
.Type 表示的是某个类型的元类型,而在 Swift 中,除了 class,struct 和 enum 这三个类型外,我们还可以定义 protocol。对于 protocol 来说,有时候我们也会想取得接口的元类型。这时我们可以在某个 protocol 的名字后面使用 .Protocol 来获取,使用的方法和 .Type 是类似的。