Swift 5.7中能否通过字符串动态使用结构体的KeyPath?
如何通过字符串构建KeyPath访问Swift结构体属性?
先定义一个遵循Codable协议的结构体:
struct Server: Codable { let cats: Int let dogs: Int let fishies: Int }
创建该结构体的实例:
let x = Server(cats: 42, dogs: 13, fishies: 777)
我们可以通过KeyPath直接访问结构体属性:
print(x[keyPath: \.dogs])
这段代码会输出13。
现在的问题是:有没有办法通过字符串来构建并使用KeyPath?比如类似下面的写法:
let str = ".dogs" print(x[keyPath: \$str])
或者:
let s = ".dogs" let k = KeyPath(fromString: s) print(x[keyPath: k])
注:我清楚存在多种其他实现方案,比如使用SQL、字典、switch语句等。本次仅聚焦上述问题,感谢理解。
解答
Swift 的 KeyPath 是编译期类型安全的特性,原生不支持直接从字符串动态生成 KeyPath。这是因为 KeyPath 的类型信息(比如 \Server.dogs 对应的类型是 KeyPath<Server, Int>)必须在编译阶段确定,而字符串属于运行时动态内容,两者的设计逻辑天然不兼容。
如果要实现「通过字符串获取对应 KeyPath」的效果,只能手动在编译期建立字符串与 KeyPath 的映射关系,比如给结构体扩展一个方法:
extension Server { static func keyPath(for propertyName: String) -> KeyPath<Server, Int>? { switch propertyName { case "cats": return \.cats case "dogs": return \.dogs case "fishies": return \.fishies default: return nil } } } // 使用示例 if let keyPath = Server.keyPath(for: "dogs") { print(x[keyPath: keyPath]) // 输出 13 }
这种方案本质是把字符串和编译期确定的 KeyPath 做静态绑定,并非真正意义上的动态生成,但能满足你想要的使用方式。需要注意的是,当结构体的属性发生变化时,要同步更新这个映射方法,否则会出现不匹配的情况。
内容的提问来源于stack exchange,提问作者Fattie
相关产品推荐
相关产品推荐

