alibaba / HandyJSON

A handy swift json-object serialization/deserialization library
Other
4.24k stars 648 forks source link

包含didSet/willSet属性同时指定映射,无法获取正确值。 #364

Open wentaozone opened 4 years ago

wentaozone commented 4 years ago

Swift 5.1 Xcode 11.3 HandyJSON: 5.0.1

我的使用场景是序列化时可以不触发didSet/willSet方法。手动设置该属性时需要触发didSet/willSet方法。

class Test: HandyJSON{
    required init() { }
   var xyzList = [String](){
        didSet{
            //do some thing
        }
   }
   func mapping(mapper: HelpingMapper) {       
    do{
        let pointer = withUnsafePointer(to: &self.xyzList, { return $0 })
        let key = Int(bitPattern: pointer)
        print("xyzList key: \(key)")
    }
    mapper <<< self.xyzList <-- "yyyList"
  }
}

原因是:xyzList放入mapper.mappingHandlers的key 和 getRawValueFrom方法中 let address = Int(bitPattern: property.address) 的地址不一致。 经验证mapper.mappingHandlers中的key 是错误的。

导致 下面方法中if方法体不能被执行,此时从dict使用key位xyzList,而不是 yyyList,导致取不到。

fileprivate func getRawValueFrom(dict: [String: Any], property: PropertyInfo, mapper: HelpingMapper) -> Any? {
    let address = Int(bitPattern: property.address)
    if let mappingHandler = mapper.getMappingHandler(key: address) {
        if let mappingPaths = mappingHandler.mappingPaths, mappingPaths.count > 0 {
            for mappingPath in mappingPaths {
                if let _value = dict.findValueBy(path: mappingPath) {
                    return _value
                }
            }
            return nil
        }
    }
    if HandyJSONConfiguration.deserializeOptions.contains(.caseInsensitive) {
        return dict[property.key.lowercased()]
    }
    return dict[property.key]
}
Sunxb commented 4 years ago

@wentaozone 同样出现了此问题,您解决了吗

wentaozone commented 4 years ago

@wentaozone 同样出现了此问题,您解决了吗

没有。绕过了这种使用方式。

r258833095 commented 2 years ago

帮你网络搬运一下,防止有些小伙伴找不到解决方法

问:为什么didSet/willSet不好使? 答:HandyJSON是直接在内存中完成赋值的,绕过了一些观察函数,导致didSet/willSet不生效。你需要手动地在序列化前后调用你自己需要处理的逻辑。

但在1.8.0版本之后,HandyJSON对dynamic类型的属性使用KVC机制处理,会触发KVO机制。所以如果你真的需要 willSet/didSet,可以将类型声明为dynamic。

`class BasicTypes: NSObject, HandyJSON { dynamic var int: Int = 0 { didSet { print("oldValue: ", oldValue) } willSet { print("newValue: ", newValue) } }

public override required init() {}

}`

这种情况要求类继承自NSObject, 且属性声明为dynamic。 并且,在1.8.0版本之后,HandyJSON提供了didFinishMapping函数作为观察逻辑的切入点。

`class BasicTypes: HandyJSON { var int: Int?

required init() {}

func didFinishMapping() {
    print("you can fill some observing logic here")
}

}`