从 Swift 4 新的键路径语法中获取字符串?
Getting string from Swift 4 new key path syntax?
如何从 Swift 4 smart keypaths 语法(例如 \Foo.bar
)中获取 字符串值 ?在这一点上,我对任何方式都很好奇,再复杂也没关系。
我喜欢将类型信息与智能密钥路径相关联的想法。但并不是所有的 API 和第 3 方都在那里。
通过 #keyPath()
编译时验证获取 属性 名称字符串的旧方法。 Swift 4 要使用 #keyPath()
,您必须将 属性 声明为 @objc
,这是我希望避免的事情。
简答:你不能。 KeyPath
抽象旨在封装来自给定根类型的潜在嵌套 属性 关键路径 。因此,导出单个 String
值在一般情况下可能没有意义。
例如,假设导出的字符串应该被解释为 根类型 的 属性 还是其嵌套类型之一的成员?至少需要导出一个字符串数组来解决这种情况...
每种类型的解决方法。话虽如此,鉴于 KeyPath
符合 Equatable
协议,您可以自己提供一个自定义的 per type 解决方案。例如:
struct Auth {
var email: String
var password: String
}
struct User {
var name: String
var auth: Auth
}
为基于 User
的密钥路径提供 扩展 :
extension PartialKeyPath where Root == User {
var stringValue: String {
switch self {
case \User.name: return "name"
case \User.auth: return "auth"
case \User.auth.email: return "auth.email"
case \User.auth.password: return "auth.password"
default: fatalError("Unexpected key path")
}
}
用法:
let name: KeyPath<User, String> = \User.name
let email: KeyPath<User, String> = \User.auth.email
print(name.stringValue) /* name */
print(email.stringValue) /* auth.email */
我真的不会推荐这种用于生产代码的解决方案,因为维护成本有点高等等。但是既然你很好奇,至少,这给了你一个前进的方向;)
对于 Objective-C 类 上的 Objective-C 属性,您可以使用 _kvcKeyPathString
property 获取它。
但是,Swift 键路径可能没有等效的字符串。 Swift 关键路径中的 objective 声明它们不需要将字段名称包含在可执行文件中。关键路径可能表示为要获取的字段偏移量序列,或要调用对象的闭包。
当然,这和你自己objective避免声明属性@objc
有直接的冲突。我相信没有内置的工具可以做你想做的事。
聚会有点晚了,但我偶然发现了一种至少从 NSObject 子类获取关键路径字符串的方法:
NSExpression(forKeyPath: \UIView.bounds).keyPath
扩展 我们可以扩展 KeyPath
来计算 属性,像这样:
extension KeyPath where Root: NSObject {
var stringValue: String {
NSExpression(forKeyPath: self).keyPath
}
}
// Usage
let stringValue = (\Foo.bar).stringValue
print(stringValue) // prints "bar"
如何从 Swift 4 smart keypaths 语法(例如 \Foo.bar
)中获取 字符串值 ?在这一点上,我对任何方式都很好奇,再复杂也没关系。
我喜欢将类型信息与智能密钥路径相关联的想法。但并不是所有的 API 和第 3 方都在那里。
通过 #keyPath()
编译时验证获取 属性 名称字符串的旧方法。 Swift 4 要使用 #keyPath()
,您必须将 属性 声明为 @objc
,这是我希望避免的事情。
简答:你不能。 KeyPath
抽象旨在封装来自给定根类型的潜在嵌套 属性 关键路径 。因此,导出单个 String
值在一般情况下可能没有意义。
例如,假设导出的字符串应该被解释为 根类型 的 属性 还是其嵌套类型之一的成员?至少需要导出一个字符串数组来解决这种情况...
每种类型的解决方法。话虽如此,鉴于 KeyPath
符合 Equatable
协议,您可以自己提供一个自定义的 per type 解决方案。例如:
struct Auth {
var email: String
var password: String
}
struct User {
var name: String
var auth: Auth
}
为基于 User
的密钥路径提供 扩展 :
extension PartialKeyPath where Root == User {
var stringValue: String {
switch self {
case \User.name: return "name"
case \User.auth: return "auth"
case \User.auth.email: return "auth.email"
case \User.auth.password: return "auth.password"
default: fatalError("Unexpected key path")
}
}
用法:
let name: KeyPath<User, String> = \User.name
let email: KeyPath<User, String> = \User.auth.email
print(name.stringValue) /* name */
print(email.stringValue) /* auth.email */
我真的不会推荐这种用于生产代码的解决方案,因为维护成本有点高等等。但是既然你很好奇,至少,这给了你一个前进的方向;)
对于 Objective-C 类 上的 Objective-C 属性,您可以使用 _kvcKeyPathString
property 获取它。
但是,Swift 键路径可能没有等效的字符串。 Swift 关键路径中的 objective 声明它们不需要将字段名称包含在可执行文件中。关键路径可能表示为要获取的字段偏移量序列,或要调用对象的闭包。
当然,这和你自己objective避免声明属性@objc
有直接的冲突。我相信没有内置的工具可以做你想做的事。
聚会有点晚了,但我偶然发现了一种至少从 NSObject 子类获取关键路径字符串的方法:
NSExpression(forKeyPath: \UIView.bounds).keyPath
扩展 KeyPath
来计算 属性,像这样:
extension KeyPath where Root: NSObject {
var stringValue: String {
NSExpression(forKeyPath: self).keyPath
}
}
// Usage
let stringValue = (\Foo.bar).stringValue
print(stringValue) // prints "bar"