swift – 使用反射来设置对象属性,而不使用setValue forKey
在
Swift中,不可能使用.setValue(…,forKey:…)
>可空类型字段,如Int? 这有一个解决方法,也就是通过覆盖对象本身中的UnVersionKey方法的setValue. 因为我正在写一个基于反射的通用对象映射器.请参阅EVReflection我想尽量减少这种手动映射. 是否有其他方式自动设置这些属性? 解决方法可以在我的库here的单元测试中找到 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 be 1") XCTAssertTrue(status.status == .NotOK,"the status should be 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 the list should have nullableType 2") XCTAssertTrue(status.list[1]?.nullableType == 3,"the second item in the 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 = [] for item in list { self.list.append(item as? Testobject) } } default: NSLog("---> setValue for key '(key)' should be handled.") } } }
当我想要解决类似的问题时,我发现了一个方法 – KVO无法设置纯Swift协议字段的值.协议必须被标记为@objc,这在我的代码库中引起了太多的痛苦.
解决方法是使用目标C运行时查找Ivar,获取字段偏移量,并使用指针设置值. 此代码在Swift 2.2的操场中运行: import Foundation class MyClass { var myInt: Int? } let instance = MyClass() // Look up the ivar,and it's offset let ivar: Ivar = class_getInstanceVariable(instance.dynamicType,"myInt") let fieldOffset = ivar_getOffset(ivar) // Pointer arithmetic to get a pointer to the field let pointerToInstance = unsafeAddressOf(instance) let pointerToField = UnsafeMutablePointer<Int?>(pointerToInstance + fieldOffset) // Set the value using the pointer pointerToField.memory = 42 assert(instance.myInt == 42) 笔记: >这可能很脆弱,你真的不应该使用这个. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |