【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 Moyaenum 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 .getcase .updateUser:return .put}}var task: Task {switch self {case .getUser:return .requestPlaincase .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 Alamofireclass 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.defaultconfiguration.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().uuidStringpendingRequests[id] = (target, completion)let cancellable = provider.request(target) { [weak self] result inself?.lock.lock()self?.cancellables.removeValue(forKey: id)self?.pendingRequests.removeValue(forKey: id)self?.lock.unlock()completion(result)}lock.lock()cancellables[id] = cancellablelock.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 inself?.lock.lock()self?.cancellables.removeValue(forKey: identifier)self?.pendingRequests.removeValue(forKey: identifier)self?.lock.unlock()request.completion(result)}cancellables[identifier] = cancellablelock.unlock()}/// 重新发起所有请求func resumeAllRequests() {lock.lock()for (id, request) in pendingRequests {let cancellable = provider.request(request.target) { [weak self] result inself?.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 Moyaclass NetworkManager {static let shared = NetworkManager()private let networkProvider = NetworkProvider.sharedprivate 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 Moyaclass ViewController: UIViewController {override func viewDidLoad() {super.viewDidLoad()// 发起获取用户信息的请求let requestIdentifier = "getUser_123"NetworkManager.shared.getUser(id: 123, identifier: requestIdentifier) { result inswitch 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来取消请求。
注意事项
- 暂停和恢复请求: HTTP请求本身不支持暂停和恢复,pause操作实际上是取消请求,resume操作需要重新发起相同的请求。
- 线程安全: 使用NSLock确保对cancellables和pendingRequests的访问是线程安全的。
- 请求标识符: 为每个请求提供唯一的标识符,以便后续管理。可以使用UUID或自定义的字符串。
- 错误处理: 根据实际需求,完善错误处理和重试机制。
- 扩展性: 可以根据项目需求,进一步扩展网络框架,例如添加更多的插件、支持多种认证方式等。
进一步优化
- 支持多种API接口: 将UserAPI扩展为包含所有需要的API接口,或者使用多个TargetType枚举。
- 响应解析: 提供统一的响应解析方法,例如使用Codable解析JSON数据。
- 缓存机制: 根据需求添加网络缓存策略,提高性能。
- 重试机制: 对于失败的请求,添加自动重试机制。
通过以上设计和实现,您将拥有一个基于Moya的灵活且功能完整的网络请求框架,能够满足设置请求超时时间、暂停和恢复请求等需求。
需要讨论可加V:Jun_Yeong-Huang
相关文章:
【iOS Swift Moya 最新请求网络框架封装通用】
【iOS Swift Moya 最新请求网络框架封装通用】 前言框架结构1.API定义(TargetType)2. 配置MoyaProvider3. 网络管理器4. 使用示例注意事项进一步优化 前言 设计一个基于Moya的网络请求框架,可以提供灵活的网络请求管理,例如设置请…...
前端批量下载文件
背景 文件管理页面,后端只提供了一个根据 file_path 和 file_name 参数下载文件的API接口。产品需要支持用户多选之后的批量下载功能。 技术实现 基础代码 先调用下载接口,获取到二进制的文件流,然后通过 a 标签完成下载。 // return [r…...
【pytorch-lightning】架构一览
pytorch-lightning是基于pytorch的一个套壳项目,适配pytorch的版本同步更新速度很快。 它将训练的几个主要流程模块化,减少重复工作,同时让支持分布式训练,不同平台的训练迁移变得更加简单。 官网链接...
MongoDB相关使用问题
1.【报错】sort operation used more than the maximum 33554432 bytes of RAM. Add an index MongoDB 排序超过内存限制,限制最大为100M。 解决方式:将内存排序改为磁盘排序 正常用法:数据量大了再排序会报错 Autowired protected MongoO…...
DevSecOps自动化在安全关键型软件开发中的实践、Helix QAC Klocwork等SAST工具应用
DevSecOps自动化对于安全关键型软件开发至关重要。 那么,什么是DevSecOps自动化?具有哪些优势?为何助力安全关键型软件开发?让我们一起来深入了解~ 什么是DevSecOps自动化? DevSecOps自动化是指在软件开发生命周期的各…...
常见的显示器分辨率及其对应的像素数量
显示器的像素数量通常由其分辨率决定,分辨率表示为水平像素数乘以垂直像素数。 720P(1280720): 像素数量:约92.16万特点:这是高清标准的一个分辨率,通常用于手机、平板电脑或小型显示器。900P&…...
TDengine + MQTT :车联网时序数据库如何高效接入
现代新能源汽车,作为一种内部系统极为复杂的交通工具,配备了大量传感器、导航设备、应用软件,这些传感器产生的数据都需要上报到车联网平台当中。对于这些车辆的状态数据(如车速、发动机转速等)、位置数据(…...
maven的中国镜像有哪些
根据您的请求,以下是一些可用的 Maven 中国镜像: 阿里云 官网:阿里云 Maven 镜像配置:<mirror><id>aliyunmaven</id><mirrorOf>*</mirrorOf><name>阿里云公共仓库</name><url>…...
ModelScope ms-swift:轻量级模型微调框架
ModelScope ms-swift:轻量级模型微调框架 介绍支持的模型支持的技术使用方法为什么选择ms-swift?结论 介绍 ModelScope ms-swift是ModelScope社区提供的一个官方框架,用于大型语言模型(LLMs)和多模态大型模型…...
深度解析与实践:HTTP 协议
一、引言 HTTP(HyperText Transfer Protocol,超文本传输协议)是 Web 应用程序、API、微服务以及几乎所有互联网通信的核心协议。虽然它是我们日常使用的基础技术,但要深刻理解其高效使用、优化以及如何避免性能瓶颈,我…...
Zookeeper是如何解决脑裂问题的?
大家好,我是锋哥。今天分享关于【Zookeeper是如何解决脑裂问题的?】面试题。希望对大家有帮助; Zookeeper是如何解决脑裂问题的? 1000道 互联网大厂Java工程师 精选面试题-Java资源分享网 Zookeeper 通过一系列的机制来防止和解决脑裂(sp…...
《Opencv》基础操作详解(5)
接上篇:《Opencv》基础操作详解(4)-CSDN博客 目录 接上篇:《Opencv》基础操作详解(4)-CSDN博客 25、轮廓近似 简介 接口用法 参数说明 返回值 代码示例 结果展示 26、轮廓最小外接圆 简介 接口用…...
AI大模型-提示工程学习笔记2
卷首语:我所知的是我自己非常无知,所以我要不断学习。 写给AI入行比较晚的小白们(比如我自己)看的,大神可以直接路过无视了。 提示词要素 提示词由以下几个要素组成: 指令:告诉模型需要完成什…...
AWS ELB基础知识
1.负载均衡器的类型 需要了解三种类型的 ELB: Application Load Balancer (ALB) **: 在 HTTP/HTTPS 层(OSI 模型的第 7 层)运行。非常适合路由 HTTP/HTTPS 流量。支持高级路由功能,例如基于 U…...
我用Ai学Android Jetpack Compose之Text
这篇开始学习各种UI元素,答案来自 通义千问,通义千问没法生成图片,图片是我补充的。 下述代码只要复制到第一个工程,做一些import操作,一般import androidx.compose包里的东西,即可看到预览效果。完整工程代…...
Robot---奇思妙想轮足机器人
1 背景 传统机器人有足式、轮式、履带式三种移动方式,每种移动方式都有各自的优缺点。轮式机器人依靠车轮在地面上移动,能源利用率高、移动速度快,但是仅以轮子与地面接触,缺乏越障能力和对复杂地形的适应能力,尤其面对…...
springcloud 介绍
Spring Cloud是一个基于Spring Boot的微服务架构解决方案集合,它提供了一套完整的工具集,用于快速构建分布式系统。在Spring Cloud的架构中,服务被拆分为一系列小型、自治的微服务,每个服务运行在其独立的进程中,并通过…...
【STM32】I2C为什么要开漏输出和上拉电阻
为什么需要使用开漏输出 防止短路:假设使用推挽结构,多个设备挂在同一总线上,当存在某一设备将某一信号驱动为高电平,而其他设备驱动为低电平,会导致短路,导致器件损坏或降低寿命。对于开漏结构࿰…...
【从零开始入门unity游戏开发之——C#篇44】C#补充知识——var隐式类型、初始化器、匿名类型
文章目录 一、var隐式类型1、var 的基本用法2、注意3、总结 二、初始化器1、类定义2、对象初始化器3、集合初始化3.1 数组初始化3.2 List<T> 初始化3.3 Dictionary<TKey, TValue> 初始化 三、匿名类型1、示例代码2、匿名类型的限制: 专栏推荐完结 一、v…...
Spring Boot 中 TypeExcludeFilter 的作用及使用示例
在Spring Boot应用程序中,TypeExcludeFilter 是一个用于过滤特定类型的组件,使之不被Spring容器自动扫描和注册为bean的工具。这在你想要排除某些类或类型(如配置类、组件等)而不希望它们参与Spring的自动装配时非常有用。 作用 …...
【ROS】Nav2源码之nav2_behavior_tree-行为树节点列表
1、行为树节点分类 在 Nav2(Navigation2)的行为树框架中,行为树节点插件按照功能分为 Action(动作节点)、Condition(条件节点)、Control(控制节点) 和 Decorator(装饰节点) 四类。 1.1 动作节点 Action 执行具体的机器人操作或任务,直接与硬件、传感器或外部系统…...
spring:实例工厂方法获取bean
spring处理使用静态工厂方法获取bean实例,也可以通过实例工厂方法获取bean实例。 实例工厂方法步骤如下: 定义实例工厂类(Java代码),定义实例工厂(xml),定义调用实例工厂ÿ…...
Qt Http Server模块功能及架构
Qt Http Server 是 Qt 6.0 中引入的一个新模块,它提供了一个轻量级的 HTTP 服务器实现,主要用于构建基于 HTTP 的应用程序和服务。 功能介绍: 主要功能 HTTP服务器功能: 支持 HTTP/1.1 协议 简单的请求/响应处理模型 支持 GET…...
[Java恶补day16] 238.除自身以外数组的乘积
给你一个整数数组 nums,返回 数组 answer ,其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积 。 题目数据 保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内。 请 不要使用除法,且在 O(n) 时间复杂度…...
AI书签管理工具开发全记录(十九):嵌入资源处理
1.前言 📝 在上一篇文章中,我们完成了书签的导入导出功能。本篇文章我们研究如何处理嵌入资源,方便后续将资源打包到一个可执行文件中。 2.embed介绍 🎯 Go 1.16 引入了革命性的 embed 包,彻底改变了静态资源管理的…...
Linux --进程控制
本文从以下五个方面来初步认识进程控制: 目录 进程创建 进程终止 进程等待 进程替换 模拟实现一个微型shell 进程创建 在Linux系统中我们可以在一个进程使用系统调用fork()来创建子进程,创建出来的进程就是子进程,原来的进程为父进程。…...
SiFli 52把Imagie图片,Font字体资源放在指定位置,编译成指定img.bin和font.bin的问题
分区配置 (ptab.json) img 属性介绍: img 属性指定分区存放的 image 名称,指定的 image 名称必须是当前工程生成的 binary 。 如果 binary 有多个文件,则以 proj_name:binary_name 格式指定文件名, proj_name 为工程 名&…...
通过MicroSip配置自己的freeswitch服务器进行调试记录
之前用docker安装的freeswitch的,启动是正常的, 但用下面的Microsip连接不上 主要原因有可能一下几个 1、通过下面命令可以看 [rootlocalhost default]# docker exec -it freeswitch fs_cli -x "sofia status profile internal"Name …...
Spring Boot + MyBatis 集成支付宝支付流程
Spring Boot MyBatis 集成支付宝支付流程 核心流程 商户系统生成订单调用支付宝创建预支付订单用户跳转支付宝完成支付支付宝异步通知支付结果商户处理支付结果更新订单状态支付宝同步跳转回商户页面 代码实现示例(电脑网站支付) 1. 添加依赖 <!…...
Monorepo架构: Nx Cloud 扩展能力与缓存加速
借助 Nx Cloud 实现项目协同与加速构建 1 ) 缓存工作原理分析 在了解了本地缓存和远程缓存之后,我们来探究缓存是如何工作的。以计算文件的哈希串为例,若后续运行任务时文件哈希串未变,系统会直接使用对应的输出和制品文件。 2 …...
