RxNetworks

0.1.0

๐ŸงšNetwork API With RxSwift + Moya + HandyJSON + Plugins.
yangKJ/RxNetworks

What's New

OO

2022-01-20T02:00:37Z

RxNetworks

Carthage compatible Releases Compatible CocoaPods Compatible Platform

๐Ÿงš. RxSwift + Moya + HandyJSON + Plugins.๐Ÿ‘’๐Ÿ‘’๐Ÿ‘’


English | ็ฎ€ไฝ“ไธญๆ–‡

This is a set of infrastructure based on RxSwift + Moya

MoyaNetwork

This module is based on the Moya encapsulated network API architecture.

  • Mainly divided into 3 parts:
    • NetworkConfig: Set the configuration information at the beginning of the program.
      • baseURL: Root path address to base URL.
      • baseParameters: Default basic parameters, like: userID, token, etc.
      • baseMethod: Default request method type.
      • updateBaseParametersWithValue: Update default base parameter value.
    • RxMoyaProvider: Add responsiveness to network requests, returning Single sequence.
    • NetworkUtil: Network related functions
      • defaultPlugin: Add default plugin.
      • transformAPISingleJSON: Transforms a Single sequence object.
      • handyConfigurationPlugin: Handles configuration plugins.
    • PluginSubType: Inherit and replace the Moya plug-in protocol to facilitate subsequent expansion.
      • configuration: After setting the network configuration information, before starting to prepare the request, this method can be used in scenarios such as key invalidation, re-acquiring the key and then automatically re-requesting the network.
      • lastNever: When the last network response is returned, this method can be used in scenarios such as key failure to re-obtain the key and then automatically re-request the network.
    • NetworkAPI: Add protocol attributes and encapsulate basic network requests based on TargetType.
      • ip: Root path address to base URL.
      • parameters: Request parameters.
      • plugins: Set network plugins.
      • stubBehavior: Whether to take the test data.
      • request: Network request method and return a Single sequence object.
    • NetworkAPIOO: OOP converter, MVP to OOP, convenient for friends who are used to OC thinking
      • cdy_ip: Root path address to base URL.
      • cdy_path: Request path.
      • cdy_parameters: Request parameters.
      • cdy_plugins: Set network plugins.
      • cdy_testJSON: Network testing json string.
      • cdy_testTime: Network test data return time, the default is half a second.
      • cdy_HTTPRequest: Network request method and return a Single sequence object.
    • NetworkX: extension function methods etc.
      • toJSON: to JSON string.
      • toDictionary: JSON string to dictionary.
      • +=: Dictionary concatenation.

๐ŸŽท - OO Example 1:

class OOViewModel: NSObject {
    
    let disposeBag = DisposeBag()
    
    let data = PublishRelay<String>()
    
    func loadData() {
        var api = NetworkAPIOO.init()
        api.cdy_ip = NetworkConfig.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 Example 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>()
    
    /// Configure the loading animation plugin
    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 Example 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) 
            .asDriver(onErrorJustReturn: [])
    }
}

๐ŸŽท - Chain Example 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("") // Exception thrown
    }
    
    func requestData(_ ip: String) -> Observable<NSDictionary> {
        return ChainAPI.test2(ip).request()
            .asObservable()
            .map { ($0 as! NSDictionary) }
            .catchAndReturn(["data": "nil"])
    }
}

๐ŸŽท - Batch Example 5:

class BatchViewModel: NSObject {
    
    let disposeBag = DisposeBag()
    
    let data = PublishRelay<NSDictionary>()
    
    /// Configure loading animation plugin
    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() {
        Single.zip(
            APIProvider.rx.request(api: BatchAPI.test),
            APIProvider.rx.request(api: BatchAPI.test2("666")),
            APIProvider.rx.request(api: BatchAPI.test3)
        ).subscribe(onSuccess: { [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)
        }, onFailure: {
            print("Network Failed: \($0)")
        }).disposed(by: disposeBag)
    }
}

MoyaPlugins

This module is mainly based on moya package network related plug-ins

  • At present, 4 plug-ins have been packaged for you to use:

๐Ÿ  - Simple to use, implement the protocol method in the API protocol, and then add the plugin to it:

var plugins: APIPlugins {
    let cache = NetworkCachePlugin(cacheType: .networkElseCache)
    let loading = NetworkLoadingPlugin.init(delayHideHUD: 0.5)
    return [loading, cache]
}

HandyJSON

This module is based on HandyJSON package network data parsing

  • Roughly divided into the following 3 parts:
    • HandyDataModel: Network outer data model
    • HandyJSONError: Parse error related
    • RxHandyJSON: HandyJSON data parsing, currently provides two parsing solutions
      • Option 1: Combine HandyDataModel model to parse out data.
      • Option 2: Parse the data of the specified key according to keyPath, the precondition is that the json data source must be in the form of a dictionary.

๐ŸŽท - Example of use in conjunction with the network part:

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)
        .asDriver(onErrorJustReturn: [])
}

CocoaPods Install

Ex: Import Network Architecture API
- pod 'RxNetworks/MoyaNetwork'

Ex: Import Model Anslysis 
- pod 'RxNetworks/HandyJSON'

Ex: Import loading animation plugin
- pod 'RxNetworks/MoyaPlugins/Loading'

Remarks

The general process is almost like this, the Demo is also written in great detail, you can check it out for yourself.๐ŸŽท

RxNetworksDemo

Tip: If you find it helpful, please help me with a star. If you have any questions or needs, you can also issue.

Thanks.๐ŸŽ‡

About the author


License

RxNetworks is available under the MIT license. See the LICENSE file for more info.


Description

  • Swift Tools
View More Packages from this Author

Dependencies

  • None
Last updated: Wed May 18 2022 19:13:00 GMT-0500 (GMT-05:00)