Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ios/107.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/asp.net-mvc/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios 从Swift 4新密钥路径语法获取字符串?_Ios_Swift_Reflection_Swift4_Key Value Coding - Fatal编程技术网

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(获取子对象)如何使用点符号递归打印路径。我不敢相信的是,镜像和键路径彼此不工作……代表苹果公司来说,这是一个多么错失的机会啊。@Ricardouart
mirror
是一个黑匣子,它的返回值没有任何保证。因此,如果你在逻辑中包含
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的字符串表示形式”: