🧚. RxSwift + Moya + HandyJSON + Plugins.👒👒👒
English | 简体中文
基于 RxSwift + Moya 搭建响应式数据绑定网络API架构
该模块主要就是基于moya封装网络相关插件
- 目前已封装10款插件供您使用:
简单使用,在API协议当中实现该协议方法,然后将插件加入其中即可:
var plugins: APIPlugins {
let cache = NetworkCachePlugin.init(options: .cacheThenNetwork)
let loading = NetworkLoadingPlugin.init(options: .init(delay: 0.5))
let warning = NetworkWarningPlugin.init()
let shared = NetworkSharedPlugin.init()
let gzip = NetworkGZipPlugin.init()
return [loading, cache, warning, shared, gzip]
}
该模块是基于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: []) // 错误时刻返回空
}
这边提供多种多样的使用方案供您选择,怎么选择就看你心情;
🎷 - 面向对象使用示例1:
class OOViewModel: NSObject {
let disposeBag = DisposeBag()
let data = PublishRelay<String>()
func loadData() {
var api = NetworkAPIOO.init()
api.cdy_ip = BoomingSetup.baseURL
api.cdy_path = "/ip"
api.cdy_method = .get
api.cdy_plugins = [NetworkLoadingPlugin.init()]
api.cdy_HTTPRequest()
.asObservable()
.compactMap{ (($0 as! NSDictionary)["origin"] as? String) }
.bind(to: data)
.disposed(by: disposeBag)
}
}
🎷 - MVP使用示例2:
enum LoadingAPI {
case test2(String)
}
extension LoadingAPI: NetworkAPI {
var ip: APIHost {
return BoomingSetup.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)
}
}
Ex: 导入网络架构API
- pod 'Booming'
Ex: 导入加载动画插件
- pod 'Booming'
- pod 'Booming/Loading'
Ex: 导入数据解析
- pod 'RxNetworks/HandyJSON'
Ex: 导入响应式模块
- pod 'RxNetworks/RxSwift'
- 🎷 邮箱地址:ykj310@126.com 🎷
- 🎸 GitHub地址:yangKJ 🎸
- 🎺 掘金地址:茶底世界之下 🎺
- 🚴🏻 简书地址:77___ 🚴🏻
当然如果您这边觉得好用对你有所帮助,请给作者一点辛苦的打赏吧。再次感谢感谢!!!
有空我也会一直更新维护优化 😁😁😁
救救孩子吧,谢谢各位老板。
🥺