如何从 Swift 中的镜像 children 中提取可选类型值?
How to extract optional typed values from Mirror children in Swift?
我有几个 swift class 看起来类似于以下内容
public class Book {
var title: String?
var date: NSDate?
}
因为有几个不同的 classes 需要访问属性,我通过 class:
的属性使用对 运行 的反射
let myBook = Book()
myBook.title = "Hello"
myBook.date = NSDate()
let mirror = Mirror(reflecting: myBook)
var propsArr = [(key: String?, value: Any)]()
let mirrorChildrenCollection = AnyRandomAccessCollection(mirror.children)!
if mirrorChildrenCollection.count > 0 {
propsArr += mirrorChildrenCollection
}
//iterate through properties
for case let (label?, value) in propsArr {
print (label, value)
if let val = value as? NSDate {
var extractedDate = val
print(extractedDate)
}
else if let val = value as? String {
var extractedTitle = val
print (extractedTitle)
}
}
但我有一个问题,即 Child objects 没有被提取,因为它们是 Any 类型并且内部可选 classes,因此不属于我的情况。如果我从 String 更改标题?到字符串,它们确实有效,但我需要使用可选类型。
我可以在上面的实现中更改什么以将数据类型保留为字符串?和日期?并仍然从镜像中提取值?
这似乎在 Swift 2.x 中是不可能的。
由于属性是可选的,因此您必须分别转换为 NSDate?
和 String?
,如下所示:
if let val = value as? NSDate? {
// val is Optional<NSDate>
}
不幸的是,编译器不允许这样做(我不确定为什么):// error: cannot downcast from 'protocol<>' to a more optional type 'NSDate?'
.
from bubuxu 提供了一个巧妙的解决方法,如果每个 属性 都有一个 Mirror
,那么该方法会起作用。镜像的 displayStyle
属性 告诉你它是不是可选的,然后你可以手动提取包裹的值。所以这会起作用:
let child = Mirror(reflecting: myBook.date)
child.displayStyle
if child.displayStyle == .Optional {
if child.children.count == 0 {
// .None
} else {
// .Some
let (_, some) = child.children.first!
if let val = some as? NSDate {
print(val)
}
}
}
但这取决于每个 属性 都有一个 Mirror
,而且您似乎无法遍历 Mirror
的子级来检索 Mirror
他们。
我有几个 swift class 看起来类似于以下内容
public class Book {
var title: String?
var date: NSDate?
}
因为有几个不同的 classes 需要访问属性,我通过 class:
的属性使用对 运行 的反射let myBook = Book()
myBook.title = "Hello"
myBook.date = NSDate()
let mirror = Mirror(reflecting: myBook)
var propsArr = [(key: String?, value: Any)]()
let mirrorChildrenCollection = AnyRandomAccessCollection(mirror.children)!
if mirrorChildrenCollection.count > 0 {
propsArr += mirrorChildrenCollection
}
//iterate through properties
for case let (label?, value) in propsArr {
print (label, value)
if let val = value as? NSDate {
var extractedDate = val
print(extractedDate)
}
else if let val = value as? String {
var extractedTitle = val
print (extractedTitle)
}
}
但我有一个问题,即 Child objects 没有被提取,因为它们是 Any 类型并且内部可选 classes,因此不属于我的情况。如果我从 String 更改标题?到字符串,它们确实有效,但我需要使用可选类型。
我可以在上面的实现中更改什么以将数据类型保留为字符串?和日期?并仍然从镜像中提取值?
这似乎在 Swift 2.x 中是不可能的。
由于属性是可选的,因此您必须分别转换为 NSDate?
和 String?
,如下所示:
if let val = value as? NSDate? {
// val is Optional<NSDate>
}
不幸的是,编译器不允许这样做(我不确定为什么):// error: cannot downcast from 'protocol<>' to a more optional type 'NSDate?'
.
Mirror
,那么该方法会起作用。镜像的 displayStyle
属性 告诉你它是不是可选的,然后你可以手动提取包裹的值。所以这会起作用:
let child = Mirror(reflecting: myBook.date)
child.displayStyle
if child.displayStyle == .Optional {
if child.children.count == 0 {
// .None
} else {
// .Some
let (_, some) = child.children.first!
if let val = some as? NSDate {
print(val)
}
}
}
但这取决于每个 属性 都有一个 Mirror
,而且您似乎无法遍历 Mirror
的子级来检索 Mirror
他们。