. RxSwift + Moya + HandyJSON + Plugins.
English | 简体中文
基于 RxSwift + Moya 搭建响应式数据绑定网络API架构
该模块是基于Moya封装的网络API架构
Observable
序列TargetType
基础上增加协议属性和封装基础网络请求
NetworkAPI
协议默认实现方案class OOViewModel: NSObject {
let disposeBag = DisposeBag()
let data = PublishRelay()
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)
}
}
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()
/// 配置加载动画插件
let APIProvider: MoyaProvider = {
let configuration = URLSessionConfiguration.default
configuration.headers = .default
configuration.timeoutIntervalForRequest = 30
let session = Moya.Session(configuration: configuration, startRequestsImmediately: false)
let loading = NetworkLoadingPlugin.init()
return MoyaProvider(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)
}
}
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: []) // 错误时刻返回空
}
}
class ChainViewModel: NSObject {
let disposeBag = DisposeBag()
let data = PublishRelay()
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 {
return ChainAPI.test.request()
.asObservable()
.map { ($0 as! NSDictionary)["origin"] as! String }
.catchAndReturn("") // 异常抛出
}
func requestData(_ ip: String) -> Observable {
return ChainAPI.test2(ip).request()
.asObservable()
.map { ($0 as! NSDictionary) }
.catchAndReturn(["data": "nil"])
}
}
class BatchViewModel: NSObject {
let disposeBag = DisposeBag()
let data = PublishRelay()
/// 配置加载动画插件
let APIProvider: MoyaProvider = {
let configuration = URLSessionConfiguration.default
configuration.headers = .default
configuration.timeoutIntervalForRequest = 30
let session = Moya.Session(configuration: configuration, startRequestsImmediately: false)
let loading = NetworkLoadingPlugin.init()
return MoyaProvider(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,
let data2 = $1 as? Dictionary,
let data3 = $2 as? Dictionary else {
return
}
data1 += data2
data1 += data3
self?.data.accept(data1)
}, onError: {
print("Network Failed: \($0)")
}).disposed(by: disposeBag)
}
}
该模块主要就是基于moya封装网络相关插件
- 简单使用,在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
封装网络数据解析
HandyDataModel
模型使用解析出data
数据keyPath
解析出指定key的数据,前提条件数据源必须字典形式- 结合网络部分使用示例:
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: []) // 错误时刻返回空
}
Ex: 导入网络架构API
- pod 'RxNetworks/MoyaNetwork'
Ex: 导入数据解析
- pod 'RxNetworks/HandyJSON'
Ex: 导入加载动画插件
- pod 'RxNetworks/MoyaPlugins/Loading'
大体流程差不多就是这样,Demo也写的很详细,大家可以自己去看看
RxNetworksDemo
提示:如果觉得有帮助,请帮忙点个星 ⭐…
谢谢.
✌️