【iOS Swift Moya 最新请求网络框架封装通用】
- 前言
-
- 框架结构
- 1.API定义(TargetType)
- [2. 配置MoyaProvider](#2. 配置MoyaProvider)
- [3. 网络管理器](#3. 网络管理器)
- [4. 使用示例](#4. 使用示例)
- 注意事项
- 进一步优化
前言
设计一个基于Moya的网络请求框架,可以提供灵活的网络请求管理,例如设置请求超时时间、暂停某个正在进行的请求等功能。以下让我们一起来设计框架示例,包括关键部分的代码实现和详细说明。
框架结构
1. API定义(TargetType) : 定义所有的API接口。
2. 网络提供者(MoyaProvider) : 配置MoyaProvider,包括自定义Session以设置请求超时时间。
3. 网络管理器、网络响应处理 : 管理请求的发起、暂停和恢复;处理网络请求的响应和错误。
4. 使用实例。
1.API定义(TargetType)
-
首先,定义一个符合TargetType协议的枚举来描述所有的API接口。例如,假设我们有一个用户相关的API:
dartimport 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对象。
dartimport 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请求,提供更方便的接口给业务层使用。
dartimport 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. 使用示例
-
下面是如何使用上述框架进行网络请求、设置超时和暂停请求的示例。
dartimport 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来取消请求。
注意事项
- 暂停和恢复请求: HTTP请求本身不支持暂停和恢复,pause操作实际上是取消请求,resume操作需要重新发起相同的请求。
- 线程安全: 使用NSLock确保对cancellables和pendingRequests的访问是线程安全的。
- 请求标识符: 为每个请求提供唯一的标识符,以便后续管理。可以使用UUID或自定义的字符串。
- 错误处理: 根据实际需求,完善错误处理和重试机制。
- 扩展性: 可以根据项目需求,进一步扩展网络框架,例如添加更多的插件、支持多种认证方式等。
进一步优化
- 支持多种API接口: 将UserAPI扩展为包含所有需要的API接口,或者使用多个TargetType枚举。
- 响应解析: 提供统一的响应解析方法,例如使用Codable解析JSON数据。
- 缓存机制: 根据需求添加网络缓存策略,提高性能。
- 重试机制: 对于失败的请求,添加自动重试机制。
通过以上设计和实现,您将拥有一个基于Moya的灵活且功能完整的网络请求框架,能够满足设置请求超时时间、暂停和恢复请求等需求。
需要讨论可加V:Jun_Yeong-Huang