My project has dozens of custom NSControls, in some cases the subclasses are many levels deep, with each level adding custom properties. I need a way to create a function where I pass one of these controls and it returns a dictionary of all its properies and their current values. It does not need to be read/write although that would be nice.
I have tried to use MIRROR, but that only returns the top subclass.
I wish to avoid manually creating dictionaries for each control as this duplicates storage requirements (after all each control already had the values in it), please it make scalablity more difficult.
This is to allow easy population of a Property Inspector Pane in a custom IDE
var result: \[String: Any\] = \[:\]
var currentClass: AnyClass? = type(of: object)
while let cls = currentClass,
cls != NSObject.self {
var count: UInt32 = 0
if let propertyList = class_copyPropertyList(cls, &count) {
for i in 0..<Int(count) {
let property = propertyList\[i\]
guard let cname = property_getName(property) else {
continue
}
let name = String(cString: cname)
// évite doublons héritage
if result\[name\] != nil {
continue
}
// lecture via KVC
if let value = object.value(forKey: name) {
result\[name\] = value
} else {
result\[name\] = NSNull()
}
}
free(propertyList)
}
currentClass = class_getSuperclass(cls)
}
return result
}
class MyBaseControl: NSControl {
@objc dynamic var borderSize: CGFloat = 2
@objc dynamic var customTitle: String = "Hello"
}
class MyButton: MyBaseControl {
@objc dynamic var isHighlightedCustom: Bool = true
@objc dynamic var iconName: String = "star"
technically that works, but requires modifications to every propertie (willset) at every level of every control. That is not possible, for multiple reason, one of which it ignores all properties that belong to the base control (ie. native properties) and duplicates the backing storage required (each control has the values in the control, and now requires a duplicate stored in “results”
I was hoping for a solution that extracts the value already in the control,
class Kingdom
{
var kingdomName : String = "Animalia"
}
class Phylum : Kingdom
{
var phylumName : String = "Chordata"
}
class Class : Phylum
{
var cclassName : String = "Mammalia"
}
class Order : Class
{
var orderName : String = "Carnivora"
}
class Family : Order
{
var familyName : String = "Canidae"
}
class Genus : Family
{
var genusName : String = "Canis"
}
class Species : Genus
{
var speciesName : String = "Canis Familiaris"
}
class Dog: Species {
var breedName : String = "Labrador"
}
let myDog = Dog()
var mirror : Mirror? = Mirror(reflecting: myDog)
repeat {
for property in mirror!.children {
print("property: \(property)")
}
mirror = mirror?.superclassMirror
} while mirror != nil