再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<Mirror.Child>
/// 属性数组,属性被包装为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
,这样其他的调用者就只能获取到你指定的反射。