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

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

前言

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

框架结构

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

1.API定义(TargetType)

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

    dart 复制代码
    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对象。

    dart 复制代码
    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: @escaping (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请求,提供更方便的接口给业务层使用。

    dart 复制代码
    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: @escaping (Result<Response, MoyaError>) -> Void) {
            networkProvider.request(.getUser(id: id), identifier: identifier, completion: completion)
        }
    
        /// 更新用户信息
        func updateUser(id: Int, parameters: [String: Any], identifier: String? = nil, completion: @escaping (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. 使用示例

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

    dart 复制代码
    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

相关推荐
melck2 分钟前
liunx日志查询常用命令总结
java·服务器·网络
【云轩】1 小时前
《混沌钟的RISC-V指令集重构》
网络·安全
goto_w1 小时前
uniapp上使用webview与浏览器交互,支持三端(android、iOS、harmonyos next)
android·vue.js·ios·uni-app·harmonyos
EasyGBS1 小时前
视频设备轨迹回放平台EasyCVR打造视频智能融合新平台,驱动智慧机场迈向数字新时代
网络·人工智能·安全·音视频
EasyGBS2 小时前
视频设备轨迹回放平台EasyCVR综合智能化,搭建运动场体育赛事直播方案
网络·安全·音视频
低头不见5 小时前
tcp的粘包拆包问题,如何解决?
网络·网络协议·tcp/ip
SKYDROID云卓小助手6 小时前
三轴云台之相机技术篇
运维·服务器·网络·数码相机·音视频
yuzhangfeng8 小时前
【云计算物理网络】从传统网络到SDN:云计算的网络演进之路
网络·云计算