目录
- 前言
- 把方法封装到协议的目的
- 协议代码
- 编写模型
- 调用端的代码
- 对象赚json字符串
- json字符串转换成模型
- demo下载地址
前言
之前为了封装URLNavigator路由框架,当要传递控制器的参数的时候,需要用到传json字符串,然后接收的时候再把json字符串转换成对象.所以今天做了这个protocol协议,只要让模型的类遵守协议,然后啥都不用写,就能直接调用方法,为了进一步封装URLNavigator做准备
把方法封装到协议的目的
protocol中,之所以放在protocol而不是class类中的原因是swift不支持多重继承class但是可以多重继承protocol,因为swift不允许继承多个类,如果用户的类继承了我们的类,那么就不能再继承其他类,这样很不方便,但是放到协议里就可以同时继承类和协议,或者继承多个协议和1个类.
假如把我们的协议改成class会报错:Multiple inheritance from classes ‘NSObject’ and ‘TdwModelToJsonString’,意思是“NSObject”和“TdwModelToJsonString”类的多重继承,因为模型的类又继承了NSObject
协议代码
第一段是制作了一个协议,里面添加了getString()方法,目的是把类对象,转换成json字符串,这个字符串,打印出来,是直接你能在网页上线解析的正确格式,支持无线嵌套,继承Codable协议的目的是为了使用里面的JSONEncoder().encode 和 JSONEncoder().encode 和JSONDecoder().decode()这2个方法来编码和解码,这个是swift 4.0以后苹果官方出的json编码解码协议里的方法
import Foundation
//定义ConvertToStringable协议,继承Codable协议,目的是使用JSONEncoder().encode 和JSONDecoder().decode()
public protocol TdwModelToJsonString: Codable{
}
extension TdwModelToJsonString {
//在协议里面实现方法getString,这样就可以让所有继承ConvertToStringable协议的类,都有默认实现方法getString
func getString()->String {
//把按照json编码成流数据
let data = try? JSONEncoder().encode(self)
guard let jsonData = data else { return "" }
//流数据转字符串
guard let jsonStr = String.init(data: jsonData, encoding: .utf8) else { return "" }
return jsonStr
}
}
//写了String类扩展,这样可以String字符串直接.点出来方法
extension String {
func jsonStrToObject<T>(_ : T.Type) -> T? where T: Codable {
//字符串转数据流
guard let data = self.data(using: .utf8) else { return nil }
//数据流转json字符串
let str = try? JSONDecoder().decode(T.self, from: data)
return str
}
}
编写模型
模型里面需要做的是知识遵守协议TdwModelToJsonString,并且给模型都添加@objc,或者在模型类前面添加@objcMembers,否则运行时候回找不到成员变量.School模型里面只添加了2个成员:name和address .重写description是为了一会打印验证结果方便,因为类对象直接打印只显示实例对象的地址
class School:NSObject, TdwModelToJsonString{//遵守我们的TdwModelToJsonString,其他啥都不用写
@objc var name:String
@objc var address:String
init(name:String,address:String) {
self.name = name
self.address = address
}
override var description:String {
return self.dictionaryWithValues(forKeys: ["name","address"]).description
}
}
Student模型,friends成员变量里面嵌套了学生模型的数组,为了验证我们的方法可以支持嵌套模型的转换,这里没有在4个成员变量前边添加@objc,而是在类前面添加了@objcMembers,这样所有能转换成oc的成员变量都暴露给oc能使用的runtime机制
@objcMembers
class Student:NSObject,Codable,TdwModelToJsonString {//遵守我们的TdwModelToJsonString,其他啥都不用写
var name:String
var age:Int
var school:School
var friends:[Student] = [Student]()
init(name:String,age:Int,school:School,friends:[Student]) {
self.name = name
self.age = age
self.school = school
self.friends = friends
}
override var description:String {
return self.dictionaryWithValues(forKeys: ["name","age","school","friends"]).description
}
}
调用端的代码
对象赚json字符串
下面代码1个学校,3个学生,每个学生的 friends是对象数组,我们把对象zhang3转化成json字符串
let QingHua = School(name: "76zhong", address: "song hua jiang bian NO.23")
let wang5 = Student(name: "wang5", age: 18, school: QingHua, friends: [])
let li4 = Student(name: "li4", age: 20, school: QingHua, friends: [])
let zhang3 = Student(name: "zhang3", age: 30,school: QingHua, friends: [li4,wang5])
let str = zhang3.getString()
print("str=",str)
jsonStr = str //保存字符串,为了下面json字符串转化成对象使用
打印结果:
str= {“age”:30,“school”:{“name”:“76zhong”,“address”:“song hua jiang bian NO.23”},“friends”:[{“age”:20,“school”:{“name”:“76zhong”,“address”:“song hua jiang bian NO.23”},“friends”:[],“name”:“li4”},{“age”:18,“school”:{“name”:“76zhong”,“address”:“song hua jiang bian NO.23”},“friends”:[],“name”:“wang5”}],“name”:“zhang3”}
把这段字符串放到在线解析json格式的网站查看正确的缩进格式,如下图:
可以看到zhang3对象别正确的转化成json字符串
json字符串转换成模型
这段代码jsonStr是类成员变量,保存了之前的json字符串
//json字符串转换成模型
guard let obj = jsonStr.jsonStrToObject(Student.self) else{
return
}
print("obj.school.address=",obj.school.address)
print("obj.friends[0]=",obj.friends[0])
print("obj.friends[0]=",obj.friends[0])
打印结果: 可以看到obj实例对象里面的成员,都被正确赋值了.
• obj.school.address= song hua jiang bian NO.23
• obj.friends[0]= [“age”: 20, “name”: li4, “friends”: <Swift.__EmptyArrayStorage 0x1c9e436e8>(
)
, “school”: [“address”: song hua jiang bian NO.23, “name”: 76zhong]]• obj= [“age”: 30, “name”: zhang3, “friends”: <TtGCs23_ContiguousArrayStorageC16tdwModelJsonDemo7Student$ 0x6000005452c0>(
[“name”: li4, “friends”: <Swift.__EmptyArrayStorage 0x1c9e436e8>()
, “age”: 20, “school”: [“address”: song hua jiang bian NO.23, “name”: 76zhong]],
[“school”: [“address”: song hua jiang bian NO.23, “name”: 76zhong], “name”: wang5, “age”: 18, “friends”: <Swift.__EmptyArrayStorage 0x1c9e436e8>()
]
)
, “school”: [“address”: song hua jiang bian NO.23, “name”: 76zhong]]
demo下载地址
请用xcode最新版12.3以上打开运行,否则无法运行
demo下载地址