Swift语法学习–基于协议进行网络请求


实现所有实体的基础协议

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()
    }
}

原创文章,作者:ItWorker,如若转载,请注明出处:https://blog.ytso.com/290602.html

(0)
上一篇 2022年10月4日
下一篇 2022年10月4日

相关推荐

发表回复

登录后才能评论