Entity.swift
// 在这个文件中,实现所有实体的基础协议的创建。项目中的所有的实体,都需要遵循这个基础协议。 import Foundation // 定义一个协议,遵循该协议的实体,可以实现从Data数据转换为实例对象的功能 protocol DecodableEntity { // 往协议中添加一个静态方法,用来将Data数据转换为实例本身。 static func parse(data : Data) -> Self? }
UserEntity.swift
// 创建一个具体的实体类 import Foundation // 在这个类里,实现用户实体类的创建,该类的实例对象可以用来存储服务器返回的数据 struct User { let name:String let hobbies:String let birthdate:String // 添加一个初始化方法,参数类型为Data init? (data:Data) { // 将参数的值转换为一个字典 guard let obj = try?JSONSerialization.jsonObject(with:data,options:[]) as? [String:Any] else { return nil} // 根据字典的键,获得相应的值 guard let name = obj["name"] as?String else { return nil} guard let hobbies = obj["hobbies"] as?String else { return nil} guard let birthdate = obj["birthdate"] as?String else { return nil} // 将这些值依次存储在三个属性中 self.name = name self.hobbies = hobbies self.birthdate = birthdate } } // 使User类遵循DecodableEntity协议 extension User: DecodableEntity { static func parse(data : Data) -> Self? { return User(data: data) } }
HttpRequest.swift
// 创建网络请求类,在这个文件中,实现网络请求的基础协议。项目中的所有网络请求,都需要遵循此文件中的协议。 import Foundation import SwiftUI enum HttpRequestMethod: String { case GET case POST case PUT case DELETE } protocol HttpRequest { var path: String { get } var method: HttpRequestMethod { get } var parameter: [String:Any] { get } // 由于所有网络请求都遵循这个协议,服务器返回的数据又是不同的,所以无法确定使用哪个实体来存储服务器的数据,因此先定义一个占位符,由该协议的遵循者决定占位符的类型 associatedtype Response: DecodableEntity } // 完成所有网络请求的基础协议之后,接着创建一个具体的网络请求者User extension HttpRequest { var host: String { return "http://hdjc8.com" } }
User.swift
// 在这个文件中,实现一个具体的网络请求,用来访问服务器上的一个接口 import Foundation struct UserHttpResquest: HttpRequest { typealias Response = User var path = "/json/jsonUser.json" let method: HttpRequestMethod = .GET let parameter: [String : Any] = [:] }
HttpClient.swift
// 网络连接模块创建 import Foundation protocol Client { // 给协议添加一个方法,为了使Client可以接收项目中的所有网络请求,在此使用泛型,并使泛型遵httpRequest协议 func send<T:HttpRequest>(_ request: T, handler: @escaping (T.Response?) -> Void) } struct HttpClient:Client { // 实现协议中的方法,以向服务器发送网络请求 func send<T:HttpRequest>(_ request: T, handler: @escaping (T.Response?) -> Void) { // 获得服务器的接口地址,并生成一URLRequest对象 let hostAndPath = request.host.appending(request.path) var urlRequest = URLRequest(url: URL(string: hostAndPath)!) // 设置网络请求方法 urlRequest.httpMethod = request.method.rawValue let dataTask = URLSession.shared.dataTask(with: urlRequest) { data, _, error in guard let data = data, let entity = T.Response.parse(data: data) else { return } // 接着返回主线程,在主线程处理生成的实体对象 DispatchQueue.main.async { handler(entity) } } // 调用resume方法,可以访问指定的网络接口,如果不是https格式,还需要修改项目配置文件 dataTask.resume() } }
ContentView.swift
import SwiftUI struct ContentView: View { @State var name : String = "" @State var birthdate : String = "" @State var hobby : String = "" var body: some View { VStack(alignment: .leading){ Text("user.name:(name)") Text("user.birthday:(birthdate)") Text("user.hobby:(hobby)") Button(action: { HttpClient().send(UserHttpResquest()) { user in if let user = user { name = user.name birthdate = user.birthdate hobby = user.hobbies } } }, label: { Text("显示结果") }) } } } struct ContentView_Previews: PreviewProvider { static var previews: some View { ContentView() } }