【iOS Swift Moya 最新请求网络框架封装通用】

【iOS Swift Moya 最新请求网络框架封装通用】

  • 前言
    • 框架结构
    • 1.API定义(TargetType)
    • 2. 配置MoyaProvider
    • 3. 网络管理器
    • 4. 使用示例
    • 注意事项
    • 进一步优化

前言

设计一个基于Moya的网络请求框架,可以提供灵活的网络请求管理,例如设置请求超时时间、暂停某个正在进行的请求等功能。以下让我们一起来设计框架示例,包括关键部分的代码实现和详细说明。

框架结构

1. API定义(TargetType): 定义所有的API接口。
2. 网络提供者(MoyaProvider): 配置MoyaProvider,包括自定义Session以设置请求超时时间。
3. 网络管理器、网络响应处理 : 管理请求的发起、暂停和恢复;处理网络请求的响应和错误。
4. 使用实例。

1.API定义(TargetType)

  • 首先,定义一个符合TargetType协议的枚举来描述所有的API接口。例如,假设我们有一个用户相关的API:

    import Moya
    
    enum UserAPI {
        case getUser(id: Int)
        case updateUser(id: Int, parameters: [String: Any])
        // 其他API接口
    }
    
    extension UserAPI: TargetType {
        var baseURL: URL {
            return URL(string: "https://api.example.com")!
        }
    
        var path: String {
            switch self {
            case .getUser(let id):
                return "/user/\(id)"
            case .updateUser(let id, _):
                return "/user/\(id)"
            }
        }
    
        var method: Moya.Method {
            switch self {
            case .getUser:
                return .get
            case .updateUser:
                return .put
            }
        }
    
        var task: Task {
            switch self {
            case .getUser:
                return .requestPlain
            case .updateUser(_, let parameters):
                return .requestParameters(parameters: parameters, encoding: JSONEncoding.default)
            }
        }
    
        var headers: [String : String]? {
            return ["Content-Type": "application/json"]
        }
    
        var sampleData: Data {
            // 提供模拟数据
            return Data()
        }
    }
    

2. 配置MoyaProvider

  • 为了设置请求超时时间,我们需要自定义Session并传递给MoyaProvider。同时,为了管理请求任务,我们需要保存Cancellable对象。

    import Moya
    import Alamofire
    
    class NetworkProvider {
        static let shared = NetworkProvider()
        
        private let provider: MoyaProvider<UserAPI>
        private var cancellables: [String: Cancellable] = [:]
        private var pendingRequests: [String: (target: UserAPI, completion: (Result<Response, MoyaError>) -> Void)] = [:]
        private let lock = NSLock()
    
        private init() {
            let configuration = URLSessionConfiguration.default
            configuration.timeoutIntervalForRequest = 30 // 设置请求超时时间为30秒
            configuration.timeoutIntervalForResource = 60 // 设置资源请求超时时间为60秒
    
            let session = Alamofire.Session(configuration: configuration)
    
            provider = MoyaProvider<UserAPI>(session: session, plugins: [NetworkLoggerPlugin()])
        }
    
        /// 发起网络请求
        func request(_ target: UserAPI,
                     identifier: String? = nil,
                     completion:  (Result<Response, MoyaError>) -> Void) {
            let id = identifier ?? UUID().uuidString
            pendingRequests[id] = (target, completion)
            let cancellable = provider.request(target) { [weak self] result in
                self?.lock.lock()
                self?.cancellables.removeValue(forKey: id)
                self?.pendingRequests.removeValue(forKey: id)
                self?.lock.unlock()
                completion(result)
            }
            lock.lock()
            cancellables[id] = cancellable
            lock.unlock()
        }
    
        /// 暂停指定的请求
        func pauseRequest(identifier: String) {
            lock.lock()
            if let cancellable = cancellables[identifier] {
                cancellable.cancel()
                cancellables.removeValue(forKey: identifier)
                // 请求已取消,保留在pendingRequests以便恢复
            }
            lock.unlock()
        }
    
        /// 暂停所有请求
        func pauseAllRequests() {
            lock.lock()
            for (id, cancellable) in cancellables {
                cancellable.cancel()
                // 请求已取消,保留在pendingRequests以便恢复
            }
            cancellables.removeAll()
            lock.unlock()
        }
    
        /// 重新发起指定的请求
        func resumeRequest(identifier: String) {
            lock.lock()
            guard let request = pendingRequests[identifier] else {
                lock.unlock()
                return
            }
            let cancellable = provider.request(request.target) { [weak self] result in
                self?.lock.lock()
                self?.cancellables.removeValue(forKey: identifier)
                self?.pendingRequests.removeValue(forKey: identifier)
                self?.lock.unlock()
                request.completion(result)
            }
            cancellables[identifier] = cancellable
            lock.unlock()
        }
    
        /// 重新发起所有请求
        func resumeAllRequests() {
            lock.lock()
            for (id, request) in pendingRequests {
                let cancellable = provider.request(request.target) { [weak self] result in
                    self?.lock.lock()
                    self?.cancellables.removeValue(forKey: id)
                    self?.pendingRequests.removeValue(forKey: id)
                    self?.lock.unlock()
                    request.completion(result)
                }
                cancellables[id] = cancellable
            }
            lock.unlock()
        }
    }
    

    说明:

    • 自定义Session: 通过URLSessionConfiguration设置请求超时时间。
    • 管理Cancellable: 使用字典cancellables来保存每个请求的Cancellable对象,通过唯一标识符管理请求的取消。
    • 请求方法: request方法用于发起请求,并保存Cancellable对象。
    • 暂停请求: pauseRequest方法通过标识符取消指定的请求,pauseAllRequests取消所有请求。

3. 网络管理器

  • 创建一个更高层次的网络管理器,用于处理不同类型的API请求,提供更方便的接口给业务层使用。

    import Foundation
    import Moya
    
    class NetworkManager {
        static let shared = NetworkManager()
        
        private let networkProvider = NetworkProvider.shared
    
        private init() {}
    
        /// 获取用户信息
        func getUser(id: Int, identifier: String? = nil, completion:  (Result<Response, MoyaError>) -> Void) {
            networkProvider.request(.getUser(id: id), identifier: identifier, completion: completion)
        }
    
        /// 更新用户信息
        func updateUser(id: Int, parameters: [String: Any], identifier: String? = nil, completion:  (Result<Response, MoyaError>) -> Void) {
            networkProvider.request(.updateUser(id: id, parameters: parameters), identifier: identifier, completion: completion)
        }
    
        /// 暂停指定请求
        func pauseRequest(identifier: String) {
            networkProvider.pauseRequest(identifier: identifier)
        }
    
        /// 暂停所有请求
        func pauseAllRequests() {
            networkProvider.pauseAllRequests()
        }
    
        /// 重新发起指定请求
        func resumeRequest(identifier: String) {
            networkProvider.resumeRequest(identifier: identifier)
        }
    
        /// 重新发起所有请求
        func resumeAllRequests() {
            networkProvider.resumeAllRequests()
        }
    
        // 其他API接口的封装
    }
    

    说明:

    • NetworkManager封装了所有的API接口调用,提供统一的入口。

    • 通过identifier参数,可以为每个请求指定唯一标识符,以便后续管理(暂停、取消等)。

    • 需要注意的是,HTTP请求本身并不支持暂停和恢复,只能取消并重新发起请求。如果实现类似暂停和恢复的功能,通常需要在请求被取消后,重新发起相同的请求。

4. 使用示例

  • 下面是如何使用上述框架进行网络请求、设置超时和暂停请求的示例。

    import UIKit
    import Moya
    
    class ViewController: UIViewController {
    
        override func viewDidLoad() {
            super.viewDidLoad()
            
            // 发起获取用户信息的请求
            let requestIdentifier = "getUser_123"
            NetworkManager.shared.getUser(id: 123, identifier: requestIdentifier) { result in
                switch result {
                case .success(let response):
                    do {
                        // 解析数据
                        let json = try response.mapJSON()
                        print("User Info: \(json)")
                    } catch {
                        print("解析错误: \(error)")
                    }
                case .failure(let error):
                    print("请求失败: \(error)")
                }
            }
            
            // 示例:在某个时刻暂停请求
            // NetworkManager.shared.pauseRequest(identifier: requestIdentifier)
            
            // 示例:在另一个时刻恢复请求
            // NetworkManager.shared.resumeRequest(identifier: requestIdentifier)
        }
    }
    

    说明:

    • 发起请求时,提供一个唯一的identifier用于后续管理。
    • 可以根据业务需求,在适当的时机调用pauseRequest或pauseAllRequests来取消请求。

注意事项

  1. 暂停和恢复请求: HTTP请求本身不支持暂停和恢复,pause操作实际上是取消请求,resume操作需要重新发起相同的请求。
  2. 线程安全: 使用NSLock确保对cancellables和pendingRequests的访问是线程安全的。
  3. 请求标识符: 为每个请求提供唯一的标识符,以便后续管理。可以使用UUID或自定义的字符串。
  4. 错误处理: 根据实际需求,完善错误处理和重试机制。
  5. 扩展性: 可以根据项目需求,进一步扩展网络框架,例如添加更多的插件、支持多种认证方式等。

进一步优化

  1. 支持多种API接口: 将UserAPI扩展为包含所有需要的API接口,或者使用多个TargetType枚举。
  2. 响应解析: 提供统一的响应解析方法,例如使用Codable解析JSON数据。
  3. 缓存机制: 根据需求添加网络缓存策略,提高性能。
  4. 重试机制: 对于失败的请求,添加自动重试机制。

通过以上设计和实现,您将拥有一个基于Moya的灵活且功能完整的网络请求框架,能够满足设置请求超时时间、暂停和恢复请求等需求。

需要讨论可加V:Jun_Yeong-Huang

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/950863.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

C语言初阶习题【25】strcpy的模拟实现

1. 首先先调用下库函数&#xff0c;看它实现了什么 2. 我们自己实现一个strcpy函数 3. 改进1 把*destnation和source 写上去&#xff0c;使用后置 4. 改进2 这里直接把赋值操作放到了while的判断条件里面&#xff0c;然后while循环语句什么都不做&#xff0c;放了一个空语句…

【超详细】MIT 液态神经网络(LNNs)——深度学习新动向

✅作者简介:双一流博士,人工智能领域学习者,深耕机器学习,交叉学科实践者。已发表SCI1/区top论文10+,授权专利4件,公开10+。可提供专利思路和指导,提供科研小工具,分享科研经验,欢迎交流! 📌个人主页: https://blog.csdn.net/allein_STR?spm=1011.2559.3001.5343…

某讯一面,有点难度

今天分享的是训练营的朋友在某讯外包的面经&#xff0c;他在面完后跟我说&#xff1a;数据一致性策略好久没问,有点忘了&#xff0c;所以这一块答的不太好。 我一直都会和大家强调复习的重要性&#xff0c;尤其是这种常见的问题。看看下面的问题你都能答得上来吗&#xff1f; …

汽车免拆诊断 | 2017 款东风风神 AX7 车热机后怠速不稳

故障现象 一辆2017款东风风神AX7车&#xff0c;搭载DFMA14T发动机&#xff0c;累计行驶里程约为13.7万km。该车冷起动后怠速运转正常&#xff0c;热机后怠速运转不稳&#xff0c;组合仪表上的发动机转速表指针上下轻微抖动。 故障诊断  用故障检测仪检测&#xff0c;发动机控…

SSL 证书格式和证书文件扩展名:完整指南

SSL 证书是什么以及它如何工作相当容易理解。但当涉及到在服务器上安装它时&#xff0c;有时&#xff0c;你可能觉得这是在处理火箭科学。 由于有如此多的SSL 证书格式与特定服务器要求相关&#xff0c;您更有可能感到困惑和沮丧&#xff0c;而不是从一开始就正确配置证书。但…

在ubuntu22.04中使用bear命令追踪内核编译报错的原因分析和解决方案

1.说明 我在ubuntu22.04中使用bear命令追踪内核编译时发生如下报错&#xff1a; 如图&#xff0c;在链接名为libexec.so的动态库时发生错误 2 分析及解决过程 打印变量 LIB 发现其为空&#xff0c;也就是说 bear会去 /usr/bear/ 去找 libexec.so 去看一下 /usr/bear/是否存…

Day10——爬虫

爬虫概念 网络请求 爬虫分类 基本流程 请求头

nacos学习笔记(一)

1.前言 何为nacos&#xff0c;nacos是一个更易于构建云原生应用的动态服务发现、配置管理和服务管理平台。可以说集注册中心&#xff0c;配置中心&#xff0c;服务管理于一起的平台。注册中心&#xff1a;相当于我们可以把服务注册到注册中心上&#xff0c;我们以后可以通过服…

机器学习周报-ModernTCN文献阅读

文章目录 摘要Abstract 0 提升有效感受野&#xff08;ERF&#xff09;1 相关知识1.1 标准卷积1.2 深度分离卷积&#xff08;Depthwise Convolution&#xff0c;DWConv&#xff09;1.3 逐点卷积&#xff08;Pointwise Convolution&#xff0c;PWConv&#xff09;1.4 组卷积(Grou…

WebRtc01: 课程导学、框架介绍

应用 难点 课程大纲 学习收获 涉及内容 概述 用途 学习收获

windows下编写的shell脚本在Linux下执行有问题解决方法

前言&#xff1a; 这个问题在实际工作中经常会遇到(非语法错误)&#xff0c;脚本来源有些是自己在windows系统编写的、有些是从别人那里copy来的&#xff0c;还有些原本是好的被别人拿到windows下修改了一些内容&#xff0c;总之各种场景&#xff0c;但是如果是一个内容比较多的…

开源CMS建站系统的安全优势有哪些?

近年来&#xff0c;用户们用开源CMS系统搭建网站的比例也越来越高&#xff0c;它为用户提供了便捷的网站建设解决方案。其中&#xff0c;亿坊CMS建站系统更因安全方面备受用户欢迎&#xff0c;下面带大家一起全面地了解一下。 一、什么是开源CMS&#xff1f; 开源CMS指的是那…

Windows系统安装Docker Desktop

文章目录 注意事项安装步骤官网下载软件安装到其它盘符操作(如果就想安装到C盘可以跳过这个步骤, 直接执行文件)等待出现软件安装界面Windows系统的配置软件的一些必要设置(以下设置需要点击apply才能生效&#xff0c;如果点不了&#xff0c;那就是安装后&#xff0c;出现了错误…

LLM 大语言模型学习记录

文章目录 1. 写在最前面2. 让 gpt-4o-mini 解释 LLM 的原理3. 让 gpt-4o-mini 解释 LLM 的使用场景4. 让 gpt-4o-mini 解释 LLM 的局限性5. 碎碎念 1. 写在最前面 大语言模型&#xff08;LLM&#xff09;似乎已经成为 AI 领域的宠儿&#xff0c;不少公司争相推出自研的大模型。…

(k8s)Flannel Error问题解决!

1.问题描述 书接上回&#xff0c;我们在解决kubectl不断重启的时候引入了Flannel 网络插件&#xff0c;但是一上来就报错&#xff0c; 2.问题解决 自己的思路&#xff1a;照例开始检查 1.先检查一下目前Flannel的pod kubectl get pods --all-namespaces 2.检查 Flannel的po…

科研绘图系列:R语言科研绘图之标记热图(heatmap)

禁止商业或二改转载,仅供自学使用,侵权必究,如需截取部分内容请后台联系作者! 文章目录 介绍加载R包数据下载导入数据数据预处理画图系统信息参考介绍 科研绘图系列:R语言科研绘图之标记热图(heatmap) 加载R包 library(tidyverse) library(ggplot2) library(reshape)…

xml格式化(1):使用python的xml库实现自闭合标签

前言 最近一段时间一直想要写一个urdf格式化插件。 至于为什么嘛&#xff0c;因为使用sw2urdf插件&#xff0c;导出的urdf&#xff0c;同一标签的内容&#xff0c;是跨行的&#xff0c;这就导致&#xff0c;内容比较乱&#xff0c;而且行数比较多。影响阅读。 因此&#xff…

5 分布式ID

这里讲一个比较常用的分布式防重复的ID生成策略&#xff0c;雪花算法 一个用户体量比较大的分布式系统必然伴随着分表分库&#xff0c;分机房部署&#xff0c;单体的部署方式肯定是承载不了这么大的体量。 雪花算法的结构说明 如下图所示: 雪花算法组成 从上图我们可以看…

Unity 热更新基础知识

文章目录 1.一些名词2.三种编译方式3.Unity 两种脚本后端3.1 Mono3.2 IL2CPP3.3 对比 1.一些名词 IL&#xff08;Intermediate Language&#xff09;&#xff1a;中间语言&#xff08;类似于汇编代码&#xff09;CIL&#xff08;Common Intermediate Language&#xff09;&…

MySQL进阶突击系列(05)突击MVCC核心原理 | 左右护法ReadView视图和undoLog版本链强强联合

2024小结&#xff1a;在写作分享上&#xff0c;这里特别感谢CSDN社区提供平台&#xff0c;支持大家持续学习分享交流&#xff0c;共同进步。社区诚意满满的干货&#xff0c;让大家收获满满。 对我而言&#xff0c;珍惜每一篇投稿分享&#xff0c;每一篇内容字数大概6000字左右&…