Ios 从Swift 4新密钥路径语法获取字符串?
如何从语法(例如,Ios 从Swift 4新密钥路径语法获取字符串?,ios,swift,reflection,swift4,key-value-coding,Ios,Swift,Reflection,Swift4,Key Value Coding,如何从语法(例如,\Foo.bar)中获取字符串值?在这一点上,我对任何方式都很好奇,不管它是否复杂 我喜欢将类型信息与智能钥匙路径相关联的想法。但并非所有的API和第三方都有 有一种通过编译时验证通过#keyPath()获取属性名字符串的旧方法。使用Swift 4使用#keyPath()时,您必须将属性声明为@objc,这是我希望避免的事情。简短回答:您不能。抽象的目的是封装来自给定根类型的潜在嵌套属性密钥路径。因此,在一般情况下,导出单个字符串值可能没有意义 例如,假设导出的字符串应该解释为
\Foo.bar
)中获取字符串值?在这一点上,我对任何方式都很好奇,不管它是否复杂
我喜欢将类型信息与智能钥匙路径相关联的想法。但并非所有的API和第三方都有
有一种通过编译时验证通过
#keyPath()
获取属性名字符串的旧方法。使用Swift 4使用#keyPath()
时,您必须将属性声明为@objc
,这是我希望避免的事情。简短回答:您不能。抽象的目的是封装来自给定根类型的潜在嵌套属性密钥路径。因此,在一般情况下,导出单个字符串值可能没有意义
例如,假设导出的字符串应该解释为根类型的属性还是其属性之一的成员?至少需要导出一个字符串数组来解决这种情况
每种类型的解决方法。话虽如此,鉴于KeyPath
符合equalable
协议,您可以自己提供定制的每种类型的解决方案。例如:
struct Auth{
var电子邮件:String
var密码:String
}
结构用户{
变量名称:String
var-auth:auth
}
为基于用户的密钥路径提供扩展:
扩展PartialKeyPath,其中Root==User{
var stringValue:String{
切换自身{
case\User.name:返回“name”
case\User.auth:返回“auth”
case\User.auth.email:返回“auth.email”
case\User.auth.password:返回“auth.password”
默认值:fatalError(“意外的密钥路径”)
}
}
用法:
let name:KeyPath=\User.name
让电子邮件发送:KeyPath=\User.auth.email
打印(name.stringValue)/*name*/
打印(email.stringValue)/*auth.email*/
考虑到维护率较高等因素,我不建议将此解决方案用于生产代码。但既然您对此感到好奇,至少这为您提供了一条前进的道路;)对于Objective-C类上的Objective-C属性,您可以使用来获得它
但是,Swift密钥路径可能没有字符串等价物。Swift密钥路径的一个既定目标是,它们不要求在可执行文件中包含字段名。密钥路径可能表示为要获取的字段偏移量序列,或调用对象的闭包
当然,这与您自己避免声明属性的目标直接冲突。我相信没有内置的工具来完成您想做的事情。有点晚了,但我偶然发现了一种从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"
很好的捕获!我在这里做了一个快速测试,不幸的是,上面提到的\u kvcKeyPathString
属性似乎只会为@objc
公开的属性返回非nil值。例如,在我上面的回答中,name
和email
键路径都是以nil
的形式返回的。请注意相关任务ion:>>但是,如果将@objc
属性添加到属性中,那么\u kvcKeyPathString
将实际具有一个值,而不是始终为nil
。使用Mirror.Children(获取子对象)如何使用点符号递归打印路径。我不敢相信的是,镜像和键路径彼此不工作……代表苹果公司来说,这是一个多么错失的机会啊。@Ricardouartmirror
是一个黑匣子,它的返回值没有任何保证。因此,如果你在逻辑中包含mirror
,那么你的逻辑就会失败K以后如果苹果改变<代码>镜像< /Case>实现,如果发生变化的方向是不可预测的,这样的破损将非常难以修复。您可以使用SuffCy生成这个BoelPoad。虽然在Swift RepL>代码>导入基础中运行时,我很容易维护好这个想法,但是类ACLASS:NSObjEC。t{var aValue:Int!};NSExpression(forKeyPath:\AClass.aValue).keyPath
@DannieP我认为这是因为您的属性是Int!
类型,这是一个可选的整数,不能暴露于目标C。但是Int
类型可能会起作用。我刚刚尝试过,对于“Int”和“NSNumber”几乎相同“@DannieP您需要使用@objc
将属性公开给Objective-C。我测试了您的示例代码(使用非可选的Int
)在Swift游乐场中,它工作得很好;)当\u kvcKeyPathString
为nil时,这似乎会崩溃,但至少它是公共API中的非\u下划线函数
替代方法。“公开API以检索KeyPath的字符串表示形式”: