IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 移动开发 -> Swift语法学习--基于协议进行网络请求 -> 正文阅读

[移动开发]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()
    }
}

结果截图

在这里插入图片描述

  移动开发 最新文章
Vue3装载axios和element-ui
android adb cmd
【xcode】Xcode常用快捷键与技巧
Android开发中的线程池使用
Java 和 Android 的 Base64
Android 测试文字编码格式
微信小程序支付
安卓权限记录
知乎之自动养号
【Android Jetpack】DataStore
上一篇文章      下一篇文章      查看所有文章
加:2022-05-09 12:51:06  更:2022-05-09 12:51:10 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/25 0:01:57-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码