<font color=red>🧚. RxSwift + Moya + HandyJSON + Plugins.👒👒👒</font>
English | 簡體中文
基於 RxSwift + Moya 搭建響應式數據綁定網絡API架構
MoyaNetwork
該模塊是基於Moya封裝的網絡API架構
- 主要分爲以下8部分:
-
NetworkConfig:在程序最開始處設置配置信息,全局通用
- addDebugging:是否開啓默認加入調試插件
- baseURL:根路徑地址
- baseParameters:默認基本參數,類似:userID,token等
- baseMethod:默認請求類型
- updateBaseParametersWithValue:更新默認基本參數數據
-
RxMoyaProvider:對網絡請求添加響應式,返回
Observable
序列 -
NetworkUtil:網絡相關函數
- defaultPlugin:添加默認插件
- transformAPIObservableJSON:轉換成可觀察序列JSON對象
- handyConfigurationPlugin:處理配置插件
-
PluginSubType:繼承替換Moya插件協議,方便後序擴展
- configuration:設置網絡配置信息之後,開始準備請求之前,該方法可以用於本地緩存存在時直接拋出數據而不用再執行後序網絡請求等場景
- lastNever:最後的最後網絡響應返回時刻,該方法可以用於密鑰失效重新去獲取密鑰然後自動再次網絡請求等場景
-
NetworkAPI:在
TargetType
基礎上增加協議屬性和封裝基礎網絡請求- ip:根路徑地址
- parameters:請求參數
- plugins:插件數組
- stubBehavior:是否走測試數據
- retry:請求失敗重試次數
- request:網絡請求方法,返回可觀察序列JSON對象
-
NetworkAPI+Ext:
NetworkAPI
協議默認實現方案 -
NetworkAPIOO:面向對象轉換器,面向協議模式轉面向對象,方便習慣OC思維的小夥伴
- cdy_ip:根路徑地址
- cdy_path:請求路徑
- cdy_parameters:請求參數
- cdy_plugins:插件
- cdy_testJSON:測試數據
- cdy_testTime:測試數據返回時間,默認半秒
- cdy_retry:請求失敗重試次數
- cdy_HTTPRequest:網絡請求方法
-
NetworkX:擴展函數方法等
- toJSON:對象轉JSON字符串
- toDictionary:JSON字符串轉字典
- +=:字典拼接
-
NetworkConfig:在程序最開始處設置配置信息,全局通用
🎷 - 面向對象使用示例1:
class OOViewModel: NSObject {
let disposeBag = DisposeBag()
let data = PublishRelay<String>()
func loadData() {
var api = NetworkAPIOO.init()
api.cdy_ip = "https://www.httpbin.org"
api.cdy_path = "/ip"
api.cdy_method = .get
api.cdy_plugins = [NetworkLoadingPlugin.init()]
api.cdy_retry = 3
api.cdy_HTTPRequest()
.asObservable()
.compactMap{ (($0 as! NSDictionary)["origin"] as? String) }
.catchAndReturn("")
.bind(to: data)
.disposed(by: disposeBag)
}
}
🎷 - MVP使用示例2:
enum LoadingAPI {
case test2(String)
}
extension LoadingAPI: NetworkAPI {
var ip: APIHost {
return NetworkConfig.baseURL
}
var path: String {
return "/post"
}
var parameters: APIParameters? {
switch self {
case .test2(let string): return ["key": string]
}
}
}
class LoadingViewModel: NSObject {
let disposeBag = DisposeBag()
let data = PublishRelay<NSDictionary>()
/// 配置加載動畫插件
let APIProvider: MoyaProvider<MultiTarget> = {
let configuration = URLSessionConfiguration.default
configuration.headers = .default
configuration.timeoutIntervalForRequest = 30
let session = Moya.Session(configuration: configuration, startRequestsImmediately: false)
let loading = NetworkLoadingPlugin.init()
return MoyaProvider<MultiTarget>(session: session, plugins: [loading])
}()
func loadData() {
APIProvider.rx.request(api: LoadingAPI.test2("666"))
.asObservable()
.subscribe { [weak self] (event) in
if let dict = event.element as? NSDictionary {
self?.data.accept(dict)
}
}.disposed(by: disposeBag)
}
}
🎷 - MVVM使用示例3:
class CacheViewModel: NSObject {
let disposeBag = DisposeBag()
struct Input {
let count: Int
}
struct Output {
let items: Driver<[CacheModel]>
}
func transform(input: Input) -> Output {
let elements = BehaviorRelay<[CacheModel]>(value: [])
let output = Output(items: elements.asDriver())
request(input.count)
.asObservable()
.bind(to: elements)
.disposed(by: disposeBag)
return output
}
}
extension CacheViewModel {
func request(_ count: Int) -> Driver<[CacheModel]> {
CacheAPI.cache(count).request()
.asObservable()
.mapHandyJSON(HandyDataModel<[CacheModel]>.self)
.compactMap { $0.data }
.observe(on: MainScheduler.instance) // 結果在主線程返回
.delay(.seconds(1), scheduler: MainScheduler.instance) // 延時1秒返回
.asDriver(onErrorJustReturn: []) // 錯誤時刻返回空
}
}
🎷 - 鏈式請求使用示例4:
class ChainViewModel: NSObject {
let disposeBag = DisposeBag()
let data = PublishRelay<NSDictionary>()
func chainLoad() {
requestIP()
.flatMapLatest(requestData)
.subscribe(onNext: { [weak self] data in
self?.data.accept(data)
}, onError: {
print("Network Failed: \($0)")
}).disposed(by: disposeBag)
}
}
extension ChainViewModel {
func requestIP() -> Observable<String> {
return ChainAPI.test.request()
.asObservable()
.map { ($0 as! NSDictionary)["origin"] as! String }
.catchAndReturn("") // 異常拋出
}
func requestData(_ ip: String) -> Observable<NSDictionary> {
return ChainAPI.test2(ip).request()
.asObservable()
.map { ($0 as! NSDictionary) }
.catchAndReturn(["data": "nil"])
}
}
🎷 - 批量請求使用示例5:
class BatchViewModel: NSObject {
let disposeBag = DisposeBag()
let data = PublishRelay<NSDictionary>()
/// 配置加載動畫插件
let APIProvider: MoyaProvider<MultiTarget> = {
let configuration = URLSessionConfiguration.default
configuration.headers = .default
configuration.timeoutIntervalForRequest = 30
let session = Moya.Session(configuration: configuration, startRequestsImmediately: false)
let loading = NetworkLoadingPlugin.init()
return MoyaProvider<MultiTarget>(session: session, plugins: [loading])
}()
func batchLoad() {
Observable.zip(
APIProvider.rx.request(api: BatchAPI.test).asObservable(),
APIProvider.rx.request(api: BatchAPI.test2("666")).asObservable(),
APIProvider.rx.request(api: BatchAPI.test3).asObservable()
).subscribe(onNext: { [weak self] in
guard var data1 = $0 as? Dictionary<String, Any>,
let data2 = $1 as? Dictionary<String, Any>,
let data3 = $2 as? Dictionary<String, Any> else {
return
}
data1 += data2
data1 += data3
self?.data.accept(data1)
}, onError: {
print("Network Failed: \($0)")
}).disposed(by: disposeBag)
}
}
MoyaPlugins
該模塊主要就是基於moya封裝網絡相關插件
- 目前已封裝6款插件供您使用:
🏠 - 簡單使用,在API協議當中實現該協議方法,然後將插件加入其中即可:
var plugins: APIPlugins {
let cache = NetworkCachePlugin(cacheType: .networkElseCache)
let loading = NetworkLoadingPlugin.init(delayHideHUD: 0.5)
loading.changeHudCallback = { (hud) in
hud.detailsLabel.textColor = UIColor.yellow
}
return [loading, cache]
}
HandyJSON
該模塊是基於HandyJSON
封裝網絡數據解析
- 大致分爲以下3個部分:
- HandyDataModel:網絡外層數據模型
- HandyJSONError:解析錯誤相關
-
RxHandyJSON:HandyJSON數據解析,目前提供兩種解析方案
-
方案1 - 結合
HandyDataModel
模型使用解析出data
數據 -
方案2 - 根據
keyPath
解析出指定key的數據,前提條件數據源必須字典形式
-
方案1 - 結合
🎷 - 結合網絡部分使用示例:
func request(_ count: Int) -> Driver<[CacheModel]> {
CacheAPI.cache(count).request()
.asObservable()
.mapHandyJSON(HandyDataModel<[CacheModel]>.self)
.compactMap { $0.data }
.observe(on: MainScheduler.instance) // 結果在主線程返回
.delay(.seconds(1), scheduler: MainScheduler.instance) // 延時1秒返回
.asDriver(onErrorJustReturn: []) // 錯誤時刻返回空
}
CocoaPods Install
Ex: 導入網絡架構API
- pod 'RxNetworks/MoyaNetwork'
Ex: 導入數據解析
- pod 'RxNetworks/HandyJSON'
Ex: 導入加載動畫插件
- pod 'RxNetworks/MoyaPlugins/Loading'
Demo
大體流程差不多就是這樣,Demo也寫的很詳細,大家可以自己去看看🎷
提示:如果覺得有幫助,請幫忙點個星 ⭐..
謝謝.🎇
- 後序有相關插件,也會慢慢補充..
✌️