使用 Mirror 进行反射
在运行时检查任意值的属性。
使用 Mirror 进行反射 是 CoddyKit 上的免费 Swift Academy 课时。 这是第 3 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 Swift Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 Swift Academy 课程共包含 4 节课。
什么是 Mirror
Mirror 是 Swift 运行时反射机制:它允许您检查值的结构,也就是其属性及其值,而无需在编译时知道具体类型。
创建 Mirror
将任意值传递给 Mirror(reflecting:):
struct Point { let x: Int; let y: Int }
let m = Mirror(reflecting: Point(x: 1, y: 2))
print(m.children.count) // 2遍历子元素
每个子元素都是一个标签和值对:
struct User { let name: String; let age: Int }
let m = Mirror(reflecting: User(name: "Ann", age: 30))
for child in m.children {
print("\(child.label ?? "?") = \(child.value)")
}
// name = Ann
// age = 30构建字段字典
反射可以将结构体展开为字典:
struct Config { let host: String; let port: Int }
let m = Mirror(reflecting: Config(host: "x", port: 80))
var dict: [String: Any] = [:]
for c in m.children { if let l = c.label { dict[l] = c.value } }
print(dict["port"]!) // 80displayStyle
Mirror 会报告一个 displayStyle,例如 .struct、.class、.enum、.tuple、.collection 等,因此您可以根据值的种类选择不同分支。
检查显示样式
检测您正在反射的值属于哪种类型:
struct S { let a = 1 }
let m = Mirror(reflecting: S())
if m.displayStyle == .struct {
print("it is a struct with \(m.children.count) field(s)")
}
// it is a struct with 1 field(s)反射元组
元组会公开按位置排列的子元素:
let m = Mirror(reflecting: (10, "hi", true))
for c in m.children { print(c.value) }
// 10
// hi
// true反射枚举
对于带有关联值的枚举情况,子元素中保存的是负载值:
enum Result2 { case ok(Int); case fail(String) }
let m = Mirror(reflecting: Result2.ok(42))
print(m.children.first?.value ?? "none") // 42通用字段打印器
反射可以实现与类型无关的工具:
func dump2(_ value: Any) {
for c in Mirror(reflecting: value).children {
print("\(c.label ?? "_"): \(c.value)")
}
}
struct Car { let make: String; let year: Int }
dump2(Car(make: "Mini", year: 2020))
// make: Mini
// year: 2020反射的开销与限制
Mirror 比直接访问更慢,而且是只读的 — 您无法通过它设置属性。请将它用于调试、日志记录和序列化辅助工具,而不要用于性能关键路径。
struct P { let v: Int }
let m = Mirror(reflecting: P(v: 5))
print(m.children.first!.value) // 5 (read only)转换反射出的值
子元素的类型为 Any;需要具体类型时,请将它们转换回相应类型:
struct Box { let count: Int; let label: String }
let m = Mirror(reflecting: Box(count: 3, label: "hi"))
for c in m.children {
if let n = c.value as? Int { print("int: \(n)") }
if let s = c.value as? String { print("str: \(s)") }
}
// int: 3
// str: hi快速检查
遍历 Mirror(reflecting: value).children 会得到什么?
回顾
您学习了 Mirror:
Mirror(reflecting:)会在运行时检查一个值children会生成标签/值对displayStyle会告诉您这是结构体、类、枚举、元组还是集合- 它是只读的且速度较慢 — 非常适合调试和序列化,但不适合性能关键路径
接下来:构建便于调试的类型。
常见问题解答
「使用 Mirror 进行反射」课时是免费的吗?
是的 — 「使用 Mirror 进行反射」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 Swift Academy 课程的其余内容,请升级到 CoddyKit PRO。 Swift Academy 课程共包含 4 节课。
「使用 Mirror 进行反射」这节课中我会学到什么?
在运行时检查任意值的属性。 你通过在浏览器中直接运行的动手代码来练习 Swift Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。
学习 Swift Academy 需要有经验吗?
无需任何先前经验。CoddyKit 上的 Swift Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 3 节课,共 4 节。
「使用 Mirror 进行反射」课时需要多长时间?
大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。
我能在这节 Swift Academy 课中编写并运行代码吗?
能。每节 Swift Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。