ObjectMapper 源码阅读笔记

协议Mappable

通常使用Mappable的时候都是自己定义的Model遵守Mappable协议,然后在func mapping(map: Map)里面完成映射,Mappable里面只有一个方法init?(map: Map) 如果返回nil 那么就会取消映射。
required init?(map: Map) {
        if code != success {
            return nil
        }
    }
     func mapping(map: Map) {
        //这里就会不执行
     }
Mappable遵守协议 BaseMappable ,有一个必须实现的方法mutating func mapping(map: Map)这边用了mutating说明该方法也可以用于struct or enum。
BaseMappable扩展了4个方法
public init?(JSONString: String, context: MapContext? = nil)
public init?(JSON: [String: Any], context: MapContext? = nil)
//初始化的方法都是返回可选的值
//MapContext是个空协议,用于给开发者传递自定义数据

public func toJSON() -> [String: Any]
public func toJSONString(prettyPrint: Bool = false) -> String?
//对应初始化方法再把数据转回去
初始化过程创建一个Map然后调用协议方法func mapping(map: Map)让开发者完成映射。
public func map(JSON: [String: Any], toObject object: N) -> N {
    var mutableObject = object
    let map = Map(mappingType: .fromJSON, JSON: JSON, toObject: true, context: context, shouldIncludeNilValues: shouldIncludeNilValues)
    mutableObject.mapping(map: map)
    return mutableObject
 }
    //shouldIncludeNilValues 是一个Bool值当设置为true时,值是空的时候,会输出NSNull。
 if map.shouldIncludeNilValues {
    basicType(NSNull(), map: map)  //If BasicType is nil, emil NSNull into the JSON output
 }

实际数据类Map

Map 是一个不能被继承的class public final class Map
Map 的部分属性权限为public internal(set)
在swift访问控制基于模块和源文件,模块就是打包的库framework,源文件就是当前工程的.swift文件,所以当前工程需要调用库里面的方法或是类需要用import "巴拉巴拉"。
//有3种访问权限
public      //都能访问
internal    //当前模块
private     //当前源文件
internal(set) //表示该属性setter为模块私有,可以看成是readOnly
Map可以用下标取值。
subscript 下标脚本让对象可以像数组字典取值的方式来获得值,下面是一个简单的例子:
class User{
    var age :Int = 30
    var name:String = "edd"
    subscript(index :Int) -> Any{
        if index == 1 {
            return age
        }
        return name
    }
}
var temp = User()[2]
//temp = edd

Mapper的取值,重载运算符

infix operator <-      //json 取值
infix operator >>>     //输出 json
运算符的位置关键字
prefix          //左
postfix         //右
infix           //中 
重载运算符可以让偷懒方法更酷炫简洁。
//改进前
func safeInt64(_ i: Any?) -> Int64{
    if let n = i as? Int64 {return n}
    if let n = i as? String{return Int64(n) ?? 0}
    guard (i as AnyObject).responds(to: #selector(getter: NSNumber.int64Value)) else {return 0}
    return (i as AnyObject).int64Value
}
let a = safeInt64("123")
//改进后
postfix operator ~!
postfix func ~!(i: Any?) -> Int64 {
    if let n = i as? Int64 {return n}
    if let n = i as? String{return Int64(n) ?? 0}
    guard (i as AnyObject).responds(to: #selector(getter: NSNumber.int64Value)) else {return 0}
    return (i as AnyObject).int64Value
}
let b = "123"~! 

泛类型

func swap(a :inout ABC, b :inout ABC){
    let  temp = a
    a = b
    b = temp
}
var aa :Int = 10
var bb :Int = 20
swap(a: &aa, b: &bb)
print(aa,bb) // 20 10
Mapper 重载了运算符 <- ,把运算符右边的 map.value()付值给左边,同时进行类型判断。
infix operator <- 
public func <- (left: inout T, right: Map) {
    switch right.mappingType {
    case .fromJSON where right.isKeyPresent:
        FromJSON.basicType(&left, object: right.value())
    case .toJSON:
        left >>> right
    default: ()
    }
}
class func basicType(_ field: inout FieldType, object: FieldType?) {
    if let value = object {
        field = value
    }
}
public func value() -> T? {
    return currentValue as? T
}
运算符左边类型如果遵守协议BaseMappable,那么就会创建Mapper
public func <- (left: inout T, right: Map) {
    switch right.mappingType {
    case .fromJSON:
        FromJSON.object(&left, map: right)
    case .toJSON:
        left >>> right
    }
}
class func object(_ field: inout N, map: Map) {
        if map.toObject {
            field = Mapper(context: map.context).map(JSONObject: map.currentValue, toObject: field)
        } else if let value: N = Mapper(context: map.context).map(JSONObject: map.currentValue) {
            field = value
        }
    }

自定义类型转换

如果接收到的数据是String,但是你又想直接拿到的时候就是转换好的数据类型,这时候就可以自定义一个class遵守TransformType协议。
var age :Double = 0
age <- (map["age"], StringToInt64Transform())
open class StringToInt64Transform: TransformType {
    public typealias Object = Int64
    public typealias JSON = String
    public init() {}
    public func transformFromJSON(_ value: Any?) -> Object?{
        return value~! //用上上面封装的偷懒方法
    }
    public func transformToJSON(_ value: Object?) -> JSON?{
        return value~!~ //~!~是吧Int64转回String
    }
    
}
也可以用闭包的方法来写自定义转换。
var age :Double = 0
age <- (map["age"], TransformOf(fromJSON: { value -> Int64? in
            return value~!
        }, toJSON: { value -> String? in
            return value~!
        }))
Mapper有封装好一些基础的类型转换。
URLTransform
EnumTransform
NSDecimalNumberTransform //精确计算用
DictionaryTransform
DataTransform 
HexColorTransform
//常用的时间转换
DateTransform
DateFormatterTransform
ISO8601DateTransform
CustomDateFormatTransform

你可能感兴趣的:(ObjectMapper 源码阅读笔记)