Skip to content

常见问题

xuyecan edited this page Sep 12, 2017 · 1 revision

问:为什么mapping函数在继承的子类里不好使?

答:因为Swift类型相关的原因,如果需要在子类里使用mapping函数,那么必须在父类(如果有多层父类,必须在最顶层的父类)里定义一个空的mapping函数,然后在子类去override它。一样情况的还有didFinishMapping函数。

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

问:怎么支持枚举类型?

答:如果你定义的枚举类型实现了RawRepresentable协议,那么可以参考: 支持枚举类型,或者使用EnumTransform:

enum EnumType: String {
    case type1, type2
}

class BasicTypes: HandyJSON {
    var type: EnumType?

    func mapping(mapper: HelpingMapper) {
        mapper <<<
            type <-- EnumTransform()
    }

    required init() {}
}

let object = BasicTypes()
object.type = EnumType.type2
print(object.toJSONString()!)
let mappedObject = BasicTypes.deserialize(from: object.toJSONString()!)!
print(mappedObject.type)

如果是非RawRepresentable的枚举,那么就需要实现定制的转换器了:

enum EnumType {
    case type1, type2
}

class BasicTypes: HandyJSON {
    var type: EnumType?

    func mapping(mapper: HelpingMapper) {
        mapper <<<
            type <-- TransformOf<EnumType, String>(fromJSON: { (rawString) -> EnumType? in
                if let _str = rawString {
                    switch (_str) {
                    case "type1":
                        return EnumType.type1
                    case "type2":
                        return EnumType.type2
                    default:
                        return nil
                    }
                }
                return nil
            }, toJSON: { (enumType) -> String? in
                if let _type = enumType {
                    switch (_type) {
                    case EnumType.type1:
                        return "type1"
                    case EnumType.type2:
                        return "type2"
                    }
                }
                return nil
            })
    }

    required init() {}
}