第三十八章 Mirror

再Objective-C中,我们可以通过Runtime来获取运行时的信息,而Swift是静态语言,虽然可以利用@objc并继承NSObject的方式获得Runtime能力,但是这并不是推荐的用法,作为静态语言,使用动态分发的能力会降低性能。

为了让Swift拥有对运行时的信息进行检测的能力,这里提供了Mirror反射,内部利用C++进行实现,具体原理点击链接去论坛探究 Mirror原理。

1. 基本使用

结构体Mirror的部分定义

public struct Mirror {
   /// 这是常用的构造方法,其他的暂时忽略,以后再补上
    public init(reflecting subject: Any)

    public typealias Child = (label: String?, value: Any)
    public typealias Children = AnyCollection

    /// 属性数组,属性被包装为Child元组
    public let children: Mirror.Children

    /// 类型(是一个枚举,定义在下面)
    public let displayStyle: Mirror.DisplayStyle?

    /// 父类的反射(同理superClass)
    public var superclassMirror: Mirror? { get }
}

Mirror.DisplayStyle枚举

public struct Mirror {
    public enum DisplayStyle {
        case `struct` // 结构体
        case `class` // 类
        case `enum` // 枚举
        case tuple // 元组
        case optional // 可选值
        case collection // 集合(数组)
        case dictionary // 字典
        case set // 集合
    }
}

示例:

class Person {
    let name: String
    let age: UInt8
    
    init(name: String, age: UInt8) {
        self.name = name
        self.age = age
    }
}

let person = Person.init(name: "Bob", age: 18)
let mirror = Mirror.init(reflecting: person)
        
for child in mirror.children {
    print("label: \(child.label!), value: \(child.value)")
}

// label: name, value: Bob
// label: age, value: 18

print(mirror.subjectType)  // Person
print(mirror.displayStyle!) // class

以上就是反射的基本使用,很方便的获取到了类的属性和值,即使被标记为private也能获取到。

2. CustomReflectable协议

CustomReflectable协议中定义了一个属性,如果实现了该协议,构造Mirror则会返回它的customMirror,而非默认实现。

public protocol CustomReflectable {

    /// The custom mirror for this instance.
    ///
    /// If this type has value semantics, the mirror should be unaffected by
    /// subsequent mutations of the instance.
    var customMirror: Mirror { get }
}

示例:

extension Person: CustomReflectable {
    var customMirror: Mirror {
        return .init(reflecting: NSObject())
    }
}

print(mirror.children.count) // 0

当我们返回NSObject()的反射作为Person的自定义反射时,我们就只能获取到NSObject()的反射,此时的children的元素为空。

由于Mirror可以获取到任意权限的结构的属性及值,为了安全起见,不希望暴露的可以通过实现CustomReflectable协议返回一个指定的customMirror,这样其他的调用者就只能获取到你指定的反射。

你可能感兴趣的:(第三十八章 Mirror)