js css htmlSwift

Swift中的Any、AnyObject、AnyClass介绍

2022-06-01  本文已影响0人  喔牛慢慢爬

概念

我们可以说AnyObject是Any的子集,Any和AnyObject都是Swift 的不确定的类型。

Any类型

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 是类似的。

参考文献

上一篇 下一篇

猜你喜欢

热点阅读