In my app I translate objects from custom classes into dictionaries so that they can be saved locally in a plist as well as on a server. I use the following to turn the properties of a class into a dictionary:
func dictionary() -> [String : Any] {
var count: UInt32 = 0;
let myClass: AnyClass = self.classForCoder;
let properties = class_copyPropertyList(myClass, &count);
var dictionaryRepresentation: [String:Any] = [:]
for i in 0..<count {
let property = properties![Int(i)]
let cStringKey = property_getName(property);
let key = String(cString: cStringKey!)
dictionaryRepresentation[key] = self.value(forKey: key) as Any
}
return dictionaryRepresentation
}
I have a problem, however, with computed properties. It seems that those are computed and the returned value gets put into the dictionary as well, which I would like to avoid. So here is my question:
Is it possible to check whether is a property computed programatically using only its name?
I am assuming this could be possible by trying to assign a value to it which would give me an error or some similar approach.
Here is what seems to be a working solution, based on suggestion by dasblinkenlight
.
Rather than using the Objective-C method outlined above, create a Mirror
of the class which has a children
made up of all settable properties, therefore excluding computables.
Used like this:
let mirror = Mirror(reflecting: MyObject)
for case let (label?, value) in mirror.children {
print (label, value)
}
Here label is the name of the variable and value is obviously the value.
EDIT: In case anyone wants to convert objects into dictionary, I am posting the full code here as well. Do however remember that if values are custom objects as well, those will need to be converted too.
func dictionary() -> [String:Any] {
let mirror = Mirror(reflecting: self)
var dictionaryRepresentation = [String:Any]()
for case let (label, value) in mirror.children {
guard let key = label else { continue }
dictionaryRepresentation[key] = value
}
return dictionaryRepresentation
}