swift - Using reflection to set object properties without using setValue forKey -


in swift it's not possible use .setvalue(..., forkey: ...)

  • nullable type fields int?
  • properties have enum it's type
  • an array of nullable objects [myobject?]

there 1 workaround , overriding setvalue forundefinedkey method in object itself.

since i'm writing general object mapper based on reflection. see evreflection minimize kind of manual mapping as possible.

is there other way set properties automatically?

the workaround can found in unit test in library here code:

class workaroundstests: xctestcase {     func testworkarounds() {         let json:string = "{\"nullabletype\": 1,\"status\": 0, \"list\": [ {\"nullabletype\": 2}, {\"nullabletype\": 3}] }"         let status = testobject(json: json)         xctasserttrue(status.nullabletype == 1, "the nullabletype should 1")         xctasserttrue(status.status == .notok, "the status should notok")         xctasserttrue(status.list.count == 2, "the list should have 2 items")         if status.list.count == 2 {             xctasserttrue(status.list[0]?.nullabletype == 2, "the first item in list should have nullabletype 2")             xctasserttrue(status.list[1]?.nullabletype == 3, "the second item in list should have nullabletype 3")         }     } }  class testobject: evobject {     enum statustype: int {         case notok = 0         case ok     }      var nullabletype: int?     var status: statustype = .ok     var list: [testobject?] = []      override func setvalue(value: anyobject!, forundefinedkey key: string) {         switch key {         case "nullabletype":             nullabletype = value as? int         case "status":             if let rawvalue = value as? int {                 status = statustype(rawvalue: rawvalue)!             }         case "list":             if let list = value as? nsarray {                 self.list = []                 item in list {                     self.list.append(item as? testobject)                 }             }         default:             nslog("---> setvalue key '\(key)' should handled.")         }     } } 

i found way around when looking solve similar problem - kvo can't set value of pure swift protocol field. protocol has marked @objc, caused pain in code base. workaround ivar using objective c runtime, field offset, , set value using pointer. code works in playground in swift 2.2:

import foundation  class myclass {     var myint: int? }  let instance = myclass()  // ivar, , it's offset let ivar: ivar = class_getinstancevariable(instance.dynamictype, "myint") let fieldoffset = ivar_getoffset(ivar)  // pointer arithmetic pointer field let pointertoinstance = unsafeaddressof(instance) let pointertofield = unsafemutablepointer<int?>(pointertoinstance + fieldoffset)  // set value using pointer pointertofield.memory = 42  assert(instance.myint == 42) 

notes:


Comments

Popular posts from this blog

javascript - Karma not able to start PhantomJS on Windows - Error: spawn UNKNOWN -

c# - Display ASPX Popup control in RowDeleteing Event (ASPX Gridview) -

Nuget pack csproj using nuspec -