您的位置:1010cc时时彩经典版 > 1010cc时时彩经典版 > 1010cc时时彩经典版凯雷德xSift互连网须要管理,怎

1010cc时时彩经典版凯雷德xSift互连网须要管理,怎

发布时间:2019-09-12 12:09编辑:1010cc时时彩经典版浏览(58)

    然后调用的时候初始化Provider就可以了,这种方式真的是...我感觉写起来很不方便,正好,Moya给我们提供了另一种好东西:Plugin.

    前段时间,公司项目重构,决定采用RxSwift,这是一个函数式响应编程的框架,我差不多也是提前学习了一点,然后就边学习边开始了,期间也是遇到了各种问题,还好项目也算是按时交付测试了。这篇文章主要是用来讲述RxSwift网络请求的用法。

    EndpointClosure

    没写什么就打印下参数,请求方法,路径..可以核对

    private func endpointMapping<Target: TargetType>(target: Target) -> Endpoint<Target> {
    print("请求连接:(target.baseURL)(target.path) n方法:(target.method)n参数:(String(describing: target.parameters)) ")
    
    
    return MoyaProvider.defaultEndpointMapping(for: target)
    }
    
    [ { "userId": 1, "id": 1, "title": "sunt aut facere repellat provident occaecati excepturi optio reprehenderit", "body": "quia et suscipit\nsuscipit recusandae consequuntur expedita et cum\nreprehenderit molestiae ut ut quas totam\nnostrum rerum est autem sunt rem eveniet architecto" }, { "userId": 1, "id": 2, "title": "qui est esse", "body": "est rerum tempore vitae\nsequi sint nihil reprehenderit dolor beatae ea dolores neque\nfugiat blanditiis voluptate porro vel nihil molestiae ut reiciendis\nqui aperiam non debitis possimus qui neque nisi nulla" }, { "userId": 1, "id": 3, "title": "ea molestias quasi exercitationem repellat qui ipsa sit aut", "body": "et iusto sed quo iure\nvoluptatem occaecati omnis eligendi aut ad\nvoluptatem doloribus vel accusantium quis pariatur\nmolestiae porro eius odio et labore et velit aut" }, { "userId": 1, "id": 4, "title": "eum et est occaecati", "body": "ullam et saepe reiciendis voluptatem adipisci\nsit amet autem assumenda provident rerum culpa\nquis hic commodi nesciunt rem tenetur doloremque ipsam iure\nquis sunt voluptatem rerum illo velit" }, ...
    

    RequestPlugin

    Moya中默认提供的3个插件

    • NetworkLoggerPlugin
    • NetworkActivityPlugin
    • HTTP Authentication
    import Moya
    import Result
    import SVProgressHUD
    class RequestPlugin: PluginType {
    
        let tk = "jKle07aY0pbSaP8ACk8_ZktK-0ivmFUTIDoLnDBw_FOSCw=="
        let accountID = "1000024"
        let tz = "Asia/Shanghai"
    
        func prepare(_ request: URLRequest, target: TargetType) -> URLRequest {
            var request = request
            request.addValue(tk, forHTTPHeaderField: "tk")
            request.addValue(accountID, forHTTPHeaderField: "accountID")
            request.addValue(tz, forHTTPHeaderField: "tz")
            return request
        }
    
        func willSend(_ request: RequestType, target: TargetType) {
               print("*****************************************************************************n请求连接:(target.baseURL)(target.path) n方法:(target.method)n参数:(String(describing: target.parameters)) ")
    
            SVProgressHUD.show()
        }
    
        func didReceive(_ result: Result<Response, MoyaError>, target: TargetType) {
    
            SVProgressHUD.dismiss()
            let result = result
            switch result {
            case .failure(let moyaError):
                switch moyaError {
                case .underlying(let error) :
                    let errorNs = error as NSError
                    print(errorNs.code)
                    break
                default:
                    break
                }
    
                break
            default:
                break
            }
        }
        func process(_ result: Result<Response, MoyaError>, target: TargetType) -> Result<Response,     MoyaError> {
            return result
        }
    
    }
    

    注意:这里可以在prepare中添加request请求头,比如一些网络访问的token.
    同时可以在此插件中添加网络访问指示器,willSend中启动指示器,didReceive中关闭指示器,process方法主要是用于对访问网络的结果进行修改再返回。另外关于MoyaError的错误我们该如何解析,需要使用到switch来先解析MoyaError,然后再解析underlying,将解析出来的Error转换成NSError,最后输入错误结果。

    NetworkLoggerPlugin可以用来进行日志的管理,NetworkActivityPlugin可以在此插件中处理状态栏中的小菊花.

    在我们的MoyaProvider中提供了三种在初始化Provider的时候的回调参数:

    JSON解析

    我们可以单独新建一个文件,用来对Moya的Response和ObservableType进行扩展

    extension Response {
        // 这一个主要是将JSON解析为单个的Model
        public func mapObject<T: BaseMappable>(_ type: T.Type) throws -> T {
            guard let json = try? JSONSerialization.jsonObject(with: self.data, options: .allowFragments) as? [String:Any] else {
                throw MoyaError.jsonMapping(self)
            }
            guard let object = Mapper<T>().map(JSONObject:json) else {
                throw MoyaError.jsonMapping(self)
            }
            return object
        }
    
        // 这个主要是将JSON解析成多个Model并返回一个数组,不同的json格式写法不相同
        public func mapArray<T: BaseMappable>(_ type: T.Type) throws -> [T] {
    
            guard let json = try? JSONSerialization.jsonObject(with: self.data, options: .allowFragments) as? [String:Any] else {
                throw MoyaError.jsonMapping(self)
            }
    
            guard let jsonDic =  json?["data"] as? [[String: Any]] else {
                throw MoyaError.jsonMapping(self)
            }
    
            guard let objects = Mapper<T>().mapArray(JSONArray: jsonDic) else {
                    throw MoyaError.jsonMapping(self)
            }
            return objects
        }
    }
    
    extension ObservableType where E == Response {
        // 这个是将JSON解析为Observable类型的Model
        public func mapObject<T: BaseMappable>(_ type: T.Type) -> Observable<T> {
            return flatMap { response -> Observable<T> in
                return Observable.just(try response.mapObject(T.self))
            }
        }
    
        // 这个是将JSON解析为Observable类型的[Model]
        public func mapArray<T: BaseMappable>(_ type: T.Type) -> Observable<[T]> {
            return flatMap { response -> Observable<[T]> in
                return Observable.just(try response.mapArray(T.self))
            }
        }
    

    Moya发送简单的网络请求

    枚举类型需满足TargetType协议

    public protocol TargetType {
    var baseURL: NSURL { get }
    var path: String { get }
    var method: Moya.Method { get }
    var parameters: [String: AnyObject]? { get }
    var sampleData: NSData { get }
    }
    

    实现一个枚举代码如下:

    import Foundation
    import Moya
    
    enum ApiManager {
    case getDantangList(String)
    case getNewsList
    case getMoreNews(String)
    case getThemeList
    case getThemeDesc(Int)
    case getNewsDesc(Int)
    case Create(title: String, body: String, userId: Int)
    case Login(phone:String,password:String)
    case Banner(String)
    }
    
    extension ApiManager: TargetType {
    /// The target's base `URL`.
    var baseURL: URL {
    switch self {
    case .Create(_,_,_):
    return URL.init(string: "http://jsonplaceholder.typicode.com/")!
    case .getDantangList,.Banner:
    return URL.init(string: "http://api.dantangapp.com/")!
    case .Login:
    return URL.init(string: "https://api.grtstar.cn")!
    default:
    return URL.init(string: "http://news-at.zhihu.com/api/")!
    }
    }
    
    /// The path to be appended to `baseURL` to form the full `URL`.
    var path: String {
    switch self {
    case .getDantangList(let page):
    return "v1/channels/(page)/items"
    case .getNewsList:
    return "4/news/latest"
    case .getMoreNews(let date):
    return "4/news/before/"   date
    case .getThemeList:
    return "4/themes"
    case .getThemeDesc(let id):
    return "4/theme/(id)"
    case .getNewsDesc(let id):
    return "4/news/(id)"
    case .Create(_, _, _):
    return "posts"
    case .Login:
    return "/rest/user/certificate"
    case .Banner:
    return "v1/banners"
    
    }
    }
    
    /// The HTTP method used in the request.
    var method: Moya.Method {
    switch self {
    
    case .Create(_, _, _):
    return .post
    case .Login:
    return .post
    default:
    return .get
    }
    
    }
    
    /// The parameters to be incoded in the request.
    var parameters: [String: Any]? {
    switch self {
    case .Create(let title, let body, let userId):
    return ["title": title, "body": body, "userId": userId]
    
    case .Login(let number, let passwords):
    return ["mobile" : number, "password" :  passwords,"deviceId": "12121312323"]
    case .Banner(let strin):
    return ["channel" :strin]
    
    default:
    return nil
    
    }
    }
    
    /// The method used for parameter encoding.
    var parameterEncoding: ParameterEncoding {
    return URLEncoding.default
    }
    
    /// Provides stub data for use in testing.
    var sampleData: Data {
    
    switch self {
    case .Create(_, _, _):
    return "Create post successfully".data(using: String.Encoding.utf8)!
    default:
    return "".data(using: String.Encoding.utf8)!
    
    }
    }
    
    var task: Task {
    return .request
    }
    
    /// Whether or not to perform Alamofire validation. Defaults to `false`.
    var validate: Bool {
    return false
    }
    }
    

    MVVM(Model-View-ViewModel)可以把数据的处理逻辑放到 ViewModel 从而大大减轻了 ViewController 的负担,是 RxSwift 中最常用的架构逻辑。

    RxSwift

    RxSwift是Swift函数响应式编程的一个开源库,由Github的ReactiveX组织开发,维护。
    RxSwift的目的是让让数据/事件流和异步任务能够更方便的序列化处理,能够使用swift进行响应式编程。
    在这里我强烈建议学习下RxSwift,尤其在使用MVVM模式下,可以实现双向绑定,下面推荐一些学习RxSwift的学习资源。
    小菁的视频

    Moya是什么就不再介绍了,因为网上已经有很多关于Moya的基础使用方法。Swift:4.1Moya: 11.0.2RxSwift: 4.1.2demo地址:

    Moya简单的介绍

    Moya是一个基于Alamofire的Networking library,并且添加了对于ReactiveCocoa和RxSwift的接口支持。

    参数说明:

    • EndpointClosure
      可以对请求参数做进一步的修改,如可以修改endpointByAddingParameters endpointByAddingHTTPHeaderFields等
    • RequestClosure 你可以在发送请求前,做点手脚. 如修改超时时间,打印一些数据等等
    • StubClosure可以设置请求的延迟时间,可以当做模拟慢速网络
    • Manager 请求网络请求的方式。默认是Alamofire
    • [PluginType]一些插件。回调的位置在发送请求后,接受服务器返回之前

    稍后详细介绍这部分内容。

    在实际应用过程中网络请求往往紧密连接着数据层,具体地说,在我们的这个例子中,一般我们需要建立一个 Post 类用来统一管理数据,类里面有 id, title, body 等信息,然后把得到的一个个 post 的 JSON 数据映射到 Post 类,也就是数据层。

    RxSwift和ObjectMapper的中间件

    新建Observable ObjectMapper.swift

    import Foundation
    import RxSwift
    import Moya
    import ObjectMapper
    import Result
    extension Observable {
        func mapObject<T: Mappable>(type: T.Type) -> Observable<T> {
            return self.map { response in
                //if response is a dictionary, then use ObjectMapper to map the dictionary
                //if not throw an error
                guard let dict = response as? [String: Any] else {
                    throw RxSwiftMoyaError.ParseJSONError
                }
    
                if let error = self.parseError(response: dict) {
                    throw error
                }
    
    
                return Mapper<T>().map(JSON: dict)!
            }
        }
    
        func mapArray<T: Mappable>(type: T.Type) -> Observable<[T]> {
            return self.map { response in
                guard let dict = response as? [[String: Any]] else {
                    throw RxSwiftMoyaError.ParseJSONError
                }
    
                if let error = self.parseError(response: dict) {
                    throw error
                }
                return Mapper<T>().mapArray(JSONArray: dicts)
            }
        }
    
        func parseServerError() -> Observable {
            return self.map { (response) in
                let name = type(of: response)
                print(name)
                guard let dict = response as? [String: Any] else {
                    throw RxSwiftMoyaError.ParseJSONError
                }
                if let error = self.parseError(response: dict) {
                    throw error
                }
                return self as! Element
            }   
        }
    
        fileprivate func parseError(response: [String: Any]?) -> NSError? {
            var error: NSError?
            if let value = response {
                var code:Int?
                var msg:String?
                if let errorDic = value["error"] as? [String:Any]{
                    code = errorDic["code"] as? Int
                    msg = errorDic["msg"] as? String
                    error = NSError(domain: "Network", code: code!, userInfo: [NSLocalizedDescriptionKey: msg ?? ""])
                }
            }
            return error
        }
    }
    
    enum RxSwiftMoyaError: String {
        case ParseJSONError
        case OtherError
    }
    extension RxSwiftMoyaError: Swift.Error {}
    

    这是以前的老版本中,需要提供Header的时候就需要这样写,非常的复杂和不方便。现在TargetType提供了headers,所以我们可以摆脱这种写法了。

    RxSwift Moya ObjectMapper 网络请求与处理

    下边介绍下Then的语法棉花糖吧,看例子吧

    _ = UILabel.init(frame: CGRect.init(x: 0, y: 0, width: kScreenW, height: 50)).then({ (make) in
    
    make.text = "Then的简单用法超赞
    		

    本文由1010cc时时彩经典版发布于1010cc时时彩经典版,转载请注明出处:1010cc时时彩经典版凯雷德xSift互连网须要管理,怎

    关键词: