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<ABC>(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 <- <T>(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<FieldType>(_ field: inout FieldType, object: FieldType?) {
    if let value = object {
        field = value
    }
}
public func value<T>() -> T? {
    return currentValue as? T
}
运算符左边类型如果遵守协议BaseMappable,那么就会创建Mapper
public func <- <T: BaseMappable>(left: inout T, right: Map) {
    switch right.mappingType {
    case .fromJSON:
        FromJSON.object(&left, map: right)
    case .toJSON:
        left >>> right
    }
}
class func object<N: BaseMappable>(_ 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
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,324评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,303评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,192评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,555评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,569评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,566评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,927评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,583评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,827评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,590评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,669评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,365评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,941评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,928评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,159评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,880评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,399评论 2 342