swift-Mirror反射


struct GitArtOS {
    var age = 18
    var name = "FGH"
    var subclassName = "二年级"
    
}

struct GitArtOSMetadata {
    var kind:        Int
    var description: UnsafeMutablePointer<GitArtOSMetadataDesc>
}

struct GitArtOSMetadataDesc {
    var flags:              UInt32
    var parent:             UInt32  // 展示用Uint32代替,实际是相同大小的结构体,
    var name:               GitArtOSDirectPointer<CChar>
    // . . .  (当前研究获取属性类型,后面的属性先不管)
    var accessFunctionPtr:       GitArtOSDirectPointer<UnsafeRawPointer>  // 不在乎具体类型,就先用UnsafeRawPointer
        var fields:                  GitArtOSDirectPointer<GitArtOSFieldDescription>  // 不在乎具体类型,就先用UnsafeRawPointer
        var numFields:               UInt32  // 属性个数
        var fieldOffsetVectorOffset: UInt32
}

struct GitArtOSDirectPointer<T>{
    var offset: Int32
    
    // 偏移offset位置,获取内容指针
    mutating func get() -> UnsafeMutablePointer<T> {
        let offset = self.offset
        // withUnsafePointer获取指针
        return withUnsafePointer(to: &self) { p in
            // UnsafeMutablePointer 返回T类型对象的指针
            // UnsafeRawPointer将p指针转换为未知类型
            // numericCast将offset转换为偏移单位数
            // advanced进行内存偏移
            // assumingMemoryBound绑定指针为T类型
            return UnsafeMutablePointer(mutating: UnsafeRawPointer(p).advanced(by: numericCast(offset)).assumingMemoryBound(to: T.self))
        }
        
    }
}


// 记录结构体内所有属性的结构
struct GitArtOSFieldDescription {
    var MangledTypeName:         GitArtOSDirectPointer<CChar>
    var Superclass:              GitArtOSDirectPointer<CChar>
    var Kind:                    UInt16
    var FieldRecordSize:         UInt16
    var NumFields:               UInt32
    var fgfields:                  GitArtOSFieldRecord // 连续存储空间 (有几个数据,就会在后面添加几个记录,通过内存平移读取)
}

// 每个属性的内容
struct GitArtOSFieldRecord {
    var flag:                    Int32
    var mangledTypeName:         GitArtOSDirectPointer<CChar>
    var fieldName:               GitArtOSDirectPointer<CChar>   // 属性名称
}


let gitartos = unsafeBitCast(GitArtOS.self as Any.Type, to:  UnsafeMutablePointer<GitArtOSMetadata>.self)
let namePtr = gitartos.pointee.description.pointee.name.get()
print(String(cString:namePtr ))
//GitArtOS
let count = gitartos.pointee.description.pointee.numFields
print("GitArtOS属性个数:\(count)")


// 单独读取第一个属性名
var fields = gitartos.pointee.description.pointee.fields.get()
let fieldRecord1Name = fields.pointee.fgfields.fieldName.get()
print(String(cString: fieldRecord1Name))

// 读取所有记录
print("----读取所有属性名----")
(0..<count).forEach { index in
    let recordPtr = withUnsafePointer(to: &fields.pointee.fgfields) {
        return UnsafeMutablePointer(mutating: UnsafeRawPointer($0).assumingMemoryBound(to: GitArtOSFieldRecord.self).advanced(by: Int(index)))
    }
    print(String(cString: recordPtr.pointee.fieldName.get()))
}

print("--GitArtOS --dump----")
dump(GitArtOS()) // 相似的实现方式

打印结果:

GitArtOS
GitArtOS属性个数:3
age
----读取所有属性名----
age
name
subclassName
--GitArtOS --dump----
▿ __lldb_expr_22.GitArtOS
  - age: 18
  - name: "FGH"
  - subclassName: "二年级"

Mirror 可以动态获取类型成员变量,在运行时可以调用方法属性等行为的特性.

  1. Mirror.swift文件
  2. 初始化方法 public init(reflecting subject: Any) 和 获取属性个数_getChildCount
  3. 类型获取 搜索_getNormalizedType:
  4. 分析结构: structMetadataRelativeDirectPointer
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章