Skip to content

Latest commit

 

History

History
322 lines (255 loc) · 11.1 KB

README_CN.md

File metadata and controls

322 lines (255 loc) · 11.1 KB

Booming

Carthage compatible CocoaPods Compatible CocoaPods Compatible Platform

🧚. RxSwift + Moya + HandyJSON/Codable + Plugins.👒👒👒


English | 简体中文

基于 RxSwift + Moya 搭建响应式数据绑定网络API架构

内置插件

该模块主要就是基于moya封装网络相关插件

  • 目前已封装14款插件供您使用:

iOS 系统:

简单使用,在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

该模块是基于HandyJSON封装网络数据解析

  • 大致分为以下3个部分:
    • HandyDataModel:网络外层数据模型
    • HandyJSONError:解析错误相关
    • RxHandyJSON:HandyJSON数据解析,目前提供两种解析方案
      • 方案1 - 结合HandyDataModel模型使用解析出data数据
      • 方案2 - 根据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: []) // 错误时刻返回空
}

HollowCodable

这个模块是序列化和反序列化数据,取代HandyJSON。

🎷 - 结合网络部分使用示例:

func request(_ count: Int) -> Observable<[CodableModel]> {
    CodableAPI.cache(count)
        .request(callbackQueue: DispatchQueue(label: "request.codable"))
        .deserialized(ApiResponse<[CodableModel]>.self, mapping: CodableModel.self)
        .compactMap({ $0.data })
        .observe(on: MainScheduler.instance)
        .catchAndReturn([])
}

如何使用

这边提供多种多样的使用方案供您选择,怎么选择就看你心情;

🎷 - 面向对象使用示例1:

class OOViewModel: NSObject {
    
    let userDefaultsCache = UserDefaults(suiteName: "userDefaultsCache")!
    
    func request(block: @escaping (String) -> Void) {
        let api = NetworkAPIOO.init()
        api.ip = "https://www.httpbin.org"
        api.path = "/headers"
        api.method = APIMethod.get
        api.plugins = [
            NetworkLoadingPlugin(options: .init(text: "OOing..")),
            NetworkCustomCachePlugin.init(cacheType: .cacheThenNetwork, cacher: userDefaultsCache),
            NetworkIgnorePlugin(pluginTypes: [NetworkActivityPlugin.self]),
        ]
        api.mapped2JSON = false
        api.request(successed: { response in
            guard let string = response.bpm.toJSONString(prettyPrint: true) else {
                return
            }
            block(string)
        })
    }
}

🎷 - 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()
            .deserialize(ApiResponse<[CacheModel]>.self)
            .compactMap { $0.data }
            .observe(on: MainScheduler.instance) // 结果在主线程返回
            .delay(.seconds(1), scheduler: MainScheduler.instance) // 延时1秒返回
            .asDriver(onErrorJustReturn: []) // 错误时刻返回空
    }
}

🎷 - 链式请求使用示例4:

class ChainViewModel: NSObject {
    
    struct Input { }
    
    struct Output {
        let data: Observable<NSDictionary>
    }
    
    func transform(input: Input) -> Output {
        let data = chain().asObservable()
        
        return Output(data: data)
    }
    
    func chain() -> Observable<NSDictionary> {
        Observable.from(optional: "begin")
            .flatMapLatest(requestIP)
            .flatMapLatest(requestData(ip:))
            .catchAndReturn([:])
    }
}

extension ChainViewModel {
    
    func requestIP(_ stirng: String) -> Observable<String> {
        return ChainAPI.test.request()
            .asObservable()
            .map { (($0 as? NSDictionary)?["origin"] as? String) ?? stirng }
            .observe(on: MainScheduler.instance)
    }
    
    func requestData(ip: String) -> Observable<NSDictionary> {
        return ChainAPI.test2(ip).request()
            .map { ($0 as! NSDictionary) }
            .catchAndReturn(["data": "nil"])
            .observe(on: MainScheduler.instance)
    }
}

🎷 - 批量请求使用示例5:

class BatchViewModel: NSObject {
    
    struct Input { }
    
    struct Output {
        let data: Observable<[String: Any]>
    }
    
    func transform(input: Input) -> Output {
        let data = batch().asObservable()
        
        return Output(data: data)
    }
    
    func batch() -> Observable<[String: Any]> {
        Observable.zip(
            BatchAPI.test.request(),
            BatchAPI.test2("666").request(),
            BatchAPI.test3.request()
        )
        .observe(on: MainScheduler.instance)
        .map { [$0, $1, $2].compactMap {
            $0 as? [String: Any]
        }}
        .map { $0.reduce([String: Any](), +==) }
        .catchAndReturn([:])
    }
}

CocoaPods Install

Ex: 导入网络架构API
- pod 'Booming'

Ex: 导入加载动画插件
- pod 'NetworkHudsPlugin'

Ex: 导入数据解析
- pod 'RxNetworks/HandyJSON'

Ex: 导入响应式模块
- pod 'RxNetworks/RxSwift'

关于作者


当然如果您这边觉得好用对你有所帮助,请给作者一点辛苦的打赏吧。再次感谢感谢!!!
有空我也会一直更新维护优化 😁😁😁

救救孩子吧,谢谢各位老板。

🥺