【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

相关推荐
web1359560970522 分钟前
桌面运维岗面试三十问
运维·网络
1024小神33 分钟前
在swiftui中使用Alamofire发送请求获取github仓库里的txt文件内容并解析
ios·github·swiftui
雪球不会消失了1 小时前
06-RabbitMQ基础
java·网络·spring cloud·mq
自由自在的小Bird2 小时前
计算机网路HTTP、TCP详解
网络·网络协议·http
komo莫莫da3 小时前
第6章——HTTP首部
网络·网络协议·http
大丈夫立于天地间3 小时前
OSPF - LSA对照表
网络·网络协议·学习·算法·信息与通信
IT 古月方源4 小时前
华为设备的监控和管理
运维·服务器·网络·安全·网络安全·华为
Eagle104fred5 小时前
pymodubs TCP 无链接报错: pymodbus.exceptions.ConnectionException: Modbus Error
网络·网络协议·tcp/ip
华为云开发者联盟5 小时前
解读ENS网络连接,面向多云多池网络的高效互联
网络·数据中心·ens·华为云stack·vpc网络
leisigoyle5 小时前
第四届智能系统、通信与计算机网络国际学术会议(ISCCN 2025)
网络·人工智能·计算机网络