網(wǎng)站運營心得推廣普通話手抄報模板可打印
【iOS Swift Moya 最新請求網(wǎng)絡(luò)框架封裝通用】
- 前言
- 框架結(jié)構(gòu)
- 1.API定義(TargetType)
- 2. 配置MoyaProvider
- 3. 網(wǎng)絡(luò)管理器
- 4. 使用示例
- 注意事項
- 進(jìn)一步優(yōu)化
前言
設(shè)計一個基于Moya的網(wǎng)絡(luò)請求框架,可以提供靈活的網(wǎng)絡(luò)請求管理,例如設(shè)置請求超時時間、暫停某個正在進(jìn)行的請求等功能。以下讓我們一起來設(shè)計框架示例,包括關(guān)鍵部分的代碼實現(xiàn)和詳細(xì)說明。
框架結(jié)構(gòu)
1. API定義(TargetType): 定義所有的API接口。
2. 網(wǎng)絡(luò)提供者(MoyaProvider): 配置MoyaProvider,包括自定義Session以設(shè)置請求超時時間。
3. 網(wǎng)絡(luò)管理器、網(wǎng)絡(luò)響應(yīng)處理 : 管理請求的發(fā)起、暫停和恢復(fù);處理網(wǎng)絡(luò)請求的響應(yīng)和錯誤。
4. 使用實例。
1.API定義(TargetType)
-
首先,定義一個符合TargetType協(xié)議的枚舉來描述所有的API接口。例如,假設(shè)我們有一個用戶相關(guān)的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 {// 提供模擬數(shù)據(jù)return Data()} }
2. 配置MoyaProvider
-
為了設(shè)置請求超時時間,我們需要自定義Session并傳遞給MoyaProvider。同時,為了管理請求任務(wù),我們需要保存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 // 設(shè)置請求超時時間為30秒configuration.timeoutIntervalForResource = 60 // 設(shè)置資源請求超時時間為60秒let session = Alamofire.Session(configuration: configuration)provider = MoyaProvider<UserAPI>(session: session, plugins: [NetworkLoggerPlugin()])}/// 發(fā)起網(wǎng)絡(luò)請求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以便恢復(fù)}lock.unlock()}/// 暫停所有請求func pauseAllRequests() {lock.lock()for (id, cancellable) in cancellables {cancellable.cancel()// 請求已取消,保留在pendingRequests以便恢復(fù)}cancellables.removeAll()lock.unlock()}/// 重新發(fā)起指定的請求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()}/// 重新發(fā)起所有請求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設(shè)置請求超時時間。
- 管理Cancellable: 使用字典cancellables來保存每個請求的Cancellable對象,通過唯一標(biāo)識符管理請求的取消。
- 請求方法: request方法用于發(fā)起請求,并保存Cancellable對象。
- 暫停請求: pauseRequest方法通過標(biāo)識符取消指定的請求,pauseAllRequests取消所有請求。
3. 網(wǎng)絡(luò)管理器
-
創(chuàng)建一個更高層次的網(wǎng)絡(luò)管理器,用于處理不同類型的API請求,提供更方便的接口給業(yè)務(wù)層使用。
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()}/// 重新發(fā)起指定請求func resumeRequest(identifier: String) {networkProvider.resumeRequest(identifier: identifier)}/// 重新發(fā)起所有請求func resumeAllRequests() {networkProvider.resumeAllRequests()}// 其他API接口的封裝 }
說明:
-
NetworkManager封裝了所有的API接口調(diào)用,提供統(tǒng)一的入口。
-
通過identifier參數(shù),可以為每個請求指定唯一標(biāo)識符,以便后續(xù)管理(暫停、取消等)。
-
需要注意的是,HTTP請求本身并不支持暫停和恢復(fù),只能取消并重新發(fā)起請求。如果實現(xiàn)類似暫停和恢復(fù)的功能,通常需要在請求被取消后,重新發(fā)起相同的請求。
-
4. 使用示例
-
下面是如何使用上述框架進(jìn)行網(wǎng)絡(luò)請求、設(shè)置超時和暫停請求的示例。
import UIKit import Moyaclass ViewController: UIViewController {override func viewDidLoad() {super.viewDidLoad()// 發(fā)起獲取用戶信息的請求let requestIdentifier = "getUser_123"NetworkManager.shared.getUser(id: 123, identifier: requestIdentifier) { result inswitch result {case .success(let response):do {// 解析數(shù)據(jù)let json = try response.mapJSON()print("User Info: \(json)")} catch {print("解析錯誤: \(error)")}case .failure(let error):print("請求失敗: \(error)")}}// 示例:在某個時刻暫停請求// NetworkManager.shared.pauseRequest(identifier: requestIdentifier)// 示例:在另一個時刻恢復(fù)請求// NetworkManager.shared.resumeRequest(identifier: requestIdentifier)} }
說明:
- 發(fā)起請求時,提供一個唯一的identifier用于后續(xù)管理。
- 可以根據(jù)業(yè)務(wù)需求,在適當(dāng)?shù)臅r機(jī)調(diào)用pauseRequest或pauseAllRequests來取消請求。
注意事項
- 暫停和恢復(fù)請求: HTTP請求本身不支持暫停和恢復(fù),pause操作實際上是取消請求,resume操作需要重新發(fā)起相同的請求。
- 線程安全: 使用NSLock確保對cancellables和pendingRequests的訪問是線程安全的。
- 請求標(biāo)識符: 為每個請求提供唯一的標(biāo)識符,以便后續(xù)管理??梢允褂肬UID或自定義的字符串。
- 錯誤處理: 根據(jù)實際需求,完善錯誤處理和重試機(jī)制。
- 擴(kuò)展性: 可以根據(jù)項目需求,進(jìn)一步擴(kuò)展網(wǎng)絡(luò)框架,例如添加更多的插件、支持多種認(rèn)證方式等。
進(jìn)一步優(yōu)化
- 支持多種API接口: 將UserAPI擴(kuò)展為包含所有需要的API接口,或者使用多個TargetType枚舉。
- 響應(yīng)解析: 提供統(tǒng)一的響應(yīng)解析方法,例如使用Codable解析JSON數(shù)據(jù)。
- 緩存機(jī)制: 根據(jù)需求添加網(wǎng)絡(luò)緩存策略,提高性能。
- 重試機(jī)制: 對于失敗的請求,添加自動重試機(jī)制。
通過以上設(shè)計和實現(xiàn),您將擁有一個基于Moya的靈活且功能完整的網(wǎng)絡(luò)請求框架,能夠滿足設(shè)置請求超時時間、暫停和恢復(fù)請求等需求。
需要討論可加V:Jun_Yeong-Huang