HandyJSON icon indicating copy to clipboard operation
HandyJSON copied to clipboard

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

Open wentaozone opened this issue 5 years ago • 3 comments

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]
}

wentaozone avatar Jan 17 '20 02:01 wentaozone

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

Sunxb avatar Sep 14 '20 11:09 Sunxb

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

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

wentaozone avatar Sep 16 '20 07:09 wentaozone

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

问:为什么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")
}

}`

r258833095 avatar Mar 07 '22 12:03 r258833095