Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can I set values for a Swift object properties using mirroring?

Right now I can inspect variables of an object using Mirror type. But can I set values for my variables using mirroring? Or maybe there's another pure-Swift way?

For example, I'd like to create an object (a Swift struct) from JSON. Is it possible without subclassing NSObject and using Objective-C functions for that?

like image 980
Randex Avatar asked Sep 30 '15 23:09

Randex


2 Answers

This was the best I can do at the moment. It is still missing converting the mirrorObject back to its generic type. FYI this is using SwiftyJSON

func convertToObject<T>(json: JSON, genericObject: T) -> T {
    let mirroredObject = Mirror(reflecting: genericObject)

    for (_, var attr) in mirroredObject.children.enumerate() {
        if let propertyName = attr.label as String! {
            attr.value = json[propertyName]
            print(propertyName)
            print(attr.value)
        }
    }
    // Figure out how to convert back to object type...
}
like image 171
mitchwinn Avatar answered Oct 30 '22 15:10

mitchwinn


This is an old question, but the answer was not working for me.

I had to change my swift object to a NSObject to make things work, and also to have dynamic properties.

In my case I use the pod Marshal to deserialize Data.

 class MyClass: NSObject, Unmarshaling
  {
       // @objc dynamic make property available for NSObject
       @objc dynamic var myProperty: String?

       required init(object: MarshaledObject) throws {
          super.init()

          initUsingReflection(object: object)
        }

        func initUsingReflection(object: MarshaledObject) {
          let mirror = Mirror(reflecting: self)

          // we go through children
          for child in mirror.children {
            guard let key = child.label else {
              continue
            }

            // This line is here to get the value from json, in my case I already know the type I needed
            let myValue: String = try! object.value(for: key)

            // The trick is here, setValue only exist in NSObject and not in swift object.
            self.setValue(myValue, forKey: key)
          }
       }
  }
like image 3
Bathilde Rocchia Avatar answered Oct 30 '22 15:10

Bathilde Rocchia