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

xoshrz7s  于 2022-11-26  发布在  iOS
关注(0)|答案(5)|浏览(768)

如何从Swift 4 smart keypaths语法(例如\Foo.bar)中获得 string value?在这一点上,我对任何方法都很好奇,不管它是否复杂。
我喜欢将类型信息与智能密钥路径相关联的想法,但并不是所有的API和第三方都有。
在Swift 4中,要使用#keyPath(),你必须声明一个属性为@objc,这是我希望避免的。

83qze16e

83qze16e1#

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

NSExpression(forKeyPath: \UIView.bounds).keyPath
vlju58qv

vlju58qv2#

简短回答:KeyPath抽象被设计用来封装一个来自给定根类型的潜在嵌套属性 key path。因此,在一般情况下,导出一个String值可能没有意义。
例如,假设导出的字符串应该被解释为 * 根类型 * 的属性还是其嵌套类型之一的成员?至少需要导出一个字符串数组来解决这种情况...

每种类型的解决方案。话虽如此,如果KeyPath符合Equatable协议,您可以自己提供一个自定义的 * 每种类型 * 的解决方案。例如:

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 */

我不会真的推荐这个解决方案用于生产代码,因为它的维护工作有些高,等等。但是,既然您对此很好奇,那么这至少为您提供了一条前进的道路;)

xfyts7mz

xfyts7mz3#

对于Objective-C类上的Objective-C属性,可以使用_kvcKeyPathString属性来获取它。
然而,Swift键路径可能没有String等价项。Swift键路径的一个明确目标是,它们不需要在可执行文件中包含字段名。键路径可能表示为要获取的字段的偏移序列,或者要在对象上调用的闭包。
当然,这与您自己避免声明@objc属性的目标直接冲突。

u4dcyp6a

u4dcyp6a4#

在@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"
bakd9h0s

bakd9h0s5#

我最近需要这样做,我想确保我从编译器得到一个静态类型检查,而不需要硬编码属性名。
如果您的属性公开给Objective-C(例如@objc),您可以使用#keyPath字串运算式。例如,您可以执行下列动作:

#keyPath(Foo.bar)
#keyPath(CALayer.postion)

请参阅Docs

相关问题