从Swift 4获取字符串新的密钥路径语法?

Dan*_*e P 28 reflection key-value-coding ios swift swift4

如何从Swift 4智能密钥路径语法中获取字符串值(例如)?在这一点上,我对任何方式都很好奇,如果它很复杂并不重要.\Foo.bar

我喜欢类型信息与智能密钥路径相关联的想法.但并非所有的API和第三方都在那里.

通过编译时验证获取属性名称字符串的旧方法#keyPath().使用Swift 4 #keyPath()你必须声明一个属性@objc,这是我宁愿避免的.

Pau*_*tos 23

简短的回答:你做不到.的KeyPath抽象设计用于包封一个潜在嵌套属性关键路径从一个给定的根类型.因此,String在一般情况下,导出单个值可能没有意义.

例如,假设导出的字符串是应该解释为根类型的属性还是其属性之一的成员?至少需要导出一个字符串数组来解决这种情况......

每种类型的解决方法.话虽如此,鉴于KeyPath符合Equatable协议,您可以自己提供自定义的每种类型的解决方案.例如:

struct Auth {
    var email: String
    var password: String
}
struct User {
    var name: String
    var auth: Auth
}
Run Code Online (Sandbox Code Playgroud)

为基于密钥的路径提供扩展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")
    }
}
Run Code Online (Sandbox Code Playgroud)

用法:

let name:  KeyPath<User, String> = \User.name
let email: KeyPath<User, String> = \User.auth.email
print(name.stringValue)  /* name */
print(email.stringValue) /* auth.email */
Run Code Online (Sandbox Code Playgroud)

我不会真的推荐这个解决方案用于生产代码,因为维护有点高,等等.但是,因为你很好奇这个,至少,给你一个前进的方法;)


And*_*ard 20

派对有点晚了,但我偶然发现了一种从NSObject子类获取密钥路径字符串的方法:

NSExpression(forKeyPath: \UIView.bounds).keyPath
Run Code Online (Sandbox Code Playgroud)

  • 当 `_kvcKeyPathString` 为 nil 时,这似乎会崩溃,但至少它是公共 API 中的非 `_underscoreFunction` 替代方案。 (2认同)

zne*_*eak 16

对于Objective-C类的Objective-C属性,您可以使用该_kvcKeyPathString属性来获取它.

但是,Swift键路径可能没有String等效项.它是Swift密钥路径的既定目标,它们不要求字段名称包含在可执行文件中.关键路径可能表示为要获取的字段偏移序列或要调用对象的闭包.

当然,这与您自己避免声明属性的目标直接冲突@objc.我相信没有内置工具可以做你想做的事.


Isl*_* Q. 15

扩展@Andy Heard 的答案,我们可以扩展KeyPath为具有计算属性,如下所示:

extension KeyPath where Root: NSObject {
    var stringValue: String {
        NSExpression(forKeyPath: self).keyPath
    }
}

// Usage
let stringValue = (\Foo.bar).stringValue
print(stringValue) // prints "bar"

Run Code Online (Sandbox Code Playgroud)