I have several swift classes that look similar like the following
public class Book {
var title: String?
var date: NSDate?
}
As there are several different classes where I need to access the properties, I am using reflection to run through the properties of the 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)
}
}
But I have a problem that the Child objects are not extracted as they are of Type Any and internally optional classes and thus do not fall into my cases. If I change title from String? to String, they do work, but I need to use optional types.
What can I change in the above implementation to leave the datatype as String? and Date? and still extract the values from the Mirror?
It seems this isn't possible in Swift 2.x.
Since the properties are optionals, you would have to cast to NSDate?
and String?
, respectively, like this:
if let val = value as? NSDate? {
// val is Optional<NSDate>
}
Unfortunately, the compiler doesn't allow this (I’m not sure why): // error: cannot downcast from 'protocol<>' to a more optional type 'NSDate?'
.
This answer from bubuxu provides a clever workaround that would work if you had a Mirror
for each property. The mirror's displayStyle
property tells you if it is an optional, and you can then extract the wrapped value manually. So this would work:
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)
}
}
}
But this depends on having a Mirror
for each property, and it seems you can’t traverse a Mirror
's children to retrieve Mirror
s for them.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With