【发布时间】:2020-08-26 23:23:27
【问题描述】:
理想情况下,我想获取 KeyPath 引用的属性的名称。但这在 Swift 中似乎不可能开箱即用。
所以我的想法是 KeyPath 可以根据开发人员添加的协议扩展提供此信息。然后我想设计一个带有初始化器/函数的 API,它接受符合该协议的 KeyPath(添加计算属性)。
到目前为止,我只能定义协议和协议的条件一致性。以下代码编译良好。
protocol KeyPathPropertyNameProviding {
var propertyName: String {get}
}
struct User {
var name: String
var age: Int
}
struct Person {
var name: String
var age: Int
}
extension KeyPath: KeyPathPropertyNameProviding where Root == Person {
var propertyName: String {
switch self {
case \Person.name: return "name"
case \Person.age: return "age"
default: return ""
}
}
}
struct PropertyWrapper<Model> {
var propertyName: String = ""
init<T>(property: KeyPath<Model, T>) {
if let property = property as? KeyPathPropertyNameProviding {
self.propertyName = property.propertyName
}
}
}
let userAge = \User.age as? KeyPathPropertyNameProviding
print(userAge?.propertyName) // "nil"
let personAge = \Person.age as? KeyPathPropertyNameProviding
print(personAge?.propertyName) // "age"
let wrapper = PropertyWrapper<Person>(property: \.age)
print(wrapper.propertyName) // "age"
但我无法限制 API,因此初始化参数 property 必须是 KeyPath 并且必须符合特定协议。
例如,以下内容会导致编译错误,但根据我的理解应该可以工作(但可能我错过了一个关键细节;))
struct PropertyWrapper<Model> {
var propertyName: String = ""
init<T>(property: KeyPath<Model, T> & KeyPathPropertyNameProviding) {
self.propertyName = property.propertyName // compilation error "Property 'propertyName' requires the types 'Model' and 'Person' be equivalent"
}
}
非常感谢任何提示!
【问题讨论】:
标签: swift