协议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