实现所有实体的基础协议
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()
}
}