从 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"