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
可以動態獲取類型、成員變量,在運行時可以調用方法、屬性等行爲的特性.
-
Mirror.swift
文件 -
初始化方法
public init(reflecting subject: Any)
和 獲取屬性個數_getChildCount
-
類型獲取 搜索
_getNormalizedType:
- 分析結構:
structMetadata
和RelativeDirectPointer