标准模型
struct Model:Codable {
let id:Int
let avatar:URL
let nickname:String
let publish:TimeInterval
}
//解析数据
do {
model = try JSONDecoder().decode(Model.self, from: data!)
} catch {
print(error)
}
//归档保存数据
do {
let data = try JSONEncoder().encode(model)
try data.write(to: path, options: Data.WritingOptions.fileProtectionMask)
} catch {
print(error)
}
//解档
do {
let data = try Data.init(contentsOf: path)
let model = try JSONDecoder().decode(Model.self, from: data!)
} catch {
print(error)
}
因为有时后台给的字段与客户端不匹配或者字段会变
如:nickname nickName
现在优化模型字段
struct Model:Codable {
let id:Int
let avatar:URL
let nickname:String
let publishTime:TimeInterval
enum CodingKeys: String, CodingKey {
case id, avatar, nickname, nickName
case publishTime = "publish"
}
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
id = try container.decodeIfPresent(Int.self, forKey: .words)
//其他的也要补齐
nickname = try container.decodeIfPresent(String.self, forKey: .nickname)
if nickname == nil{
nickname = try container.decodeIfPresent(String.self, forKey: .niceName)
}
}
}
因为模型里是时间戳,如果需要转换为时间字符串
而且有的模型需要进行Array index索引,所以要继承Equatable协议
enum EnumType:String,Codable {
case H5 = "H5"
case APP = "APP"
}
struct Model:Codable,Equatable{
let id:Int
let avatar:URL
let type: EnumType
let nickname:String
private let publishTime:TimeInterval//如果不使用可以私有
var publishTimeString: String{
get{
let date = Date.init(timeIntervalSince1970: publishTime/1000)
let formatter = DateFormatter()
formatter.dateFormat = "MM-dd HH:mm"
return formatter.string(from: date)
}
}
enum CodingKeys: String, CodingKey {
case id, avatar, nickname
case publishTime = "publish"
}
}
上面的代码有一个问题,如果产品更新,枚举类型变多了,不更新会报错
所以我们要重写 Codable协议
enum EnumType:String,Codable {
case H5 = "H5"
case APP = "APP"
case `defult`
init(from decoder: Decoder) throws {
let container = try decoder.singleValueContainer()
//这里只是一个样例,具体解析可以写的更完善
self = EnumType(rawValue: try container.decode(String.self)) ?? . defult
}
/***
init(from decoder: Decoder) throws {
do {
let container = try decoder.singleValueContainer()
let rawValue = try container.decode(String.self)
self = EnumType(rawValue: rawValue) ?? . defult
} catch {
throw error
}
}
***/
}
struct Model:Codable,Equatable{
let id:Int
let avatar:URL
let type: EnumType
let nickname:String
private let publishTime:TimeInterval//如果不使用可以私有
var publishTimeString: String{
get{
let date = Date.init(timeIntervalSince1970: publishTime/1000)
let formatter = DateFormatter()
formatter.dateFormat = "MM-dd HH:mm"
return formatter.string(from: date)
}
}
enum CodingKeys: String, CodingKey {
case id, avatar, nickname, niceName//let不添加niceName
case publishTime = "publish"
}
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
id = try container.decodeIfPresent(Int.self, forKey: .words)
//其他的也要补齐
nickname = try container.decodeIfPresent(String.self, forKey: . nickname)
if nickname == nil{
nickname = try container.decodeIfPresent(String.self, forKey: . niceName)
}
}
}
使用经历
因为模型是一步一步优化过来的,所以尝试过其他方案
比如 lazy ,但是struct用lazy在使用的时候会报错,需要用muting func去实现,有一点麻烦
有的时候只需要修改一个数据名称,CodingKeys需要全部写,xcode没有自动生成
网友评论