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

结果截图

在这里插入图片描述

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

血月无华AUV

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值