swift – 使用反射来设置对象属性,而不使用setValue forKey

swift – 使用反射来设置对象属性,而不使用setValue forKey,第1张

概述在 Swift中,不可能使用.setValue(…,forKey:…) >可空类型字段,如Int? >具有枚举类型的属性 >一个可空对象的数组,如[MyObject?] 这有一个解决方法,也就是通过覆盖对象本身中的UnVersionKey方法的setValue. 因为我正在写一个基于反射的通用对象映射器.请参阅EVReflection我想尽量减少这种手动映射. 是否有其他方式自动设置这些属性? 解 在 Swift中,不可能使用.setValue(…,forKey:…)

>可空类型字段,如Int?
>具有枚举类型的属性
>一个可空对象的数组,如[MyObject?]

这有一个解决方法,也就是通过覆盖对象本身中的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 Foundationclass MyClass{    var myInt: Int?}let instance = MyClass()// Look up the ivar,and it's offsetlet ivar: Ivar = class_getInstanceVariable(instance.dynamicType,"myInt")let fIEldOffset = ivar_getoffset(ivar)// Pointer arithmetic to get a pointer to the fIEldlet pointerToInstance = unsafeAddressOf(instance)let pointerToFIEld = UnsafeMutablePointer<Int?>(pointerToInstance + fIEldOffset)// Set the value using the pointerpointerToFIEld.memory = 42assert(instance.myInt == 42)

笔记:

>这可能很脆弱,你真的不应该使用这个.
>但是,也许它可以生活在经过彻底测试和更新的反射库中,直到Swift得到适当的反射API.
>与Mirror内部不太相像,请参阅Reflection.mm中的代码:https://github.com/apple/swift/blob/swift-2.2-branch/stdlib/public/runtime/Reflection.mm#L719
>同样的技术适用于KVO拒绝的其他类型,但是您需要注意使用正确的UnsafeMutablePointer类型.特别是与40或16字节的协议变量,不同于8位(64位)的简单类可选.参见Mike Ash关于Swift内存布局的主题:https://mikeash.com/pyblog/friday-qa-2014-08-01-exploring-swift-memory-layout-part-ii.html

总结

以上是内存溢出为你收集整理的swift – 使用反射来设置对象属性,而不使用setValue forKey全部内容,希望文章能够帮你解决swift – 使用反射来设置对象属性,而不使用setValue forKey所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: https://www.outofmemory.cn/web/1040105.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-24
下一篇 2022-05-24

发表评论

登录后才能评论

评论列表(0条)

保存