宗旨设置,RAV4xSift互联网请求管理

  在使用Alamofire开始展览互连网请求的时候,相信大部分的同桌都会卷入两个虚幻的NetworkLayer,如”APIManager”
或然”NetworkModel”等等。不过地点业务作用增添,会稳步混合各种请求,不够明晰,而Moya能很好地解决那类难题。Moya在Alamofire基础上开始展览包装,是一个同意中度自定义的互连网层,能够依照具体的须求进行接口的安装。具体的牵线能够参见莫亚的官方链接,结构图如下:

  在使用Alamofire开始展览互联网请求的时候,相信超过1/三的校友都会卷入贰个虚幻的NetworkLayer,如”APIManager”
或许”NetworkModel”等等。可是地方业务职能扩充,会日趋混合各类请求,不够清楚,而Moya能很好地消除那类难题。莫亚在Alamofire基础上海展览中心开打包,是二个同意中度自定义的网络层,能够依照现实的需要开始展览接口的设置。具体的牵线能够参见Moya的法定链接,结构图如下:

透过HTTPHeader设置公共请求参数

在其实开采中大家兴许会须要在呼吁头内增多一些公共请求参数,如用于识别部分平台标记、辨别接口的版本号。你能够定义叁个Endpoint的闭包.

let endpointClosure = { (target: T) -> Endpoint<T> in

let url = target.baseURL.appendingPathComponent(target.path).absoluteString

let endpoint = Endpoint<T>(url: url, sampleResponseClosure: { 
   .networkResponse(200, target.sampleData) }, 
    method: target.method, 
    parameters: target.parameters, 
    parameterEncoding: target.parameterEncoding)

 return endpoint.adding(newHTTPHeaderFields: 
                        ["x-platform" : "iOS", 
                        "x-interface-version" : "1.0"])}

接下来在开创请求的Provider把它增加上去

let provider = RxMoyaProvider<APIManager>(endpointClosure: endpointClosure)

前些日子,公司项目重构,决定选择福睿斯x斯威夫特,那是一个函数式响应编制程序的框架,小编繁多也是提前攻读了有些,然后就边上学边开首了,时期也是遭逢了各个难点,幸好项目也终于按期交付测试了。那篇小说首假设用来讲述奔驰G级xSwift互联网请求的用法。

澳门葡京备用网址 1

澳门葡京备用网址 2

经过插件的办法监听网络状态

普通我们会在实行互联网请求的时候实香港行政局部气象显示,如loading,那么您能够因此插件的艺术来落到实处。Moya暗中同意有七个插件:

AccessTokenPlugin 管理AccessToken的插件

CredentialsPlugin 管理认证的插件

NetworkActivityPlugin 管理网络状态的插件

NetworkLoggerPlugin 管理网络log的插件

在此地就演示一下NetworkActivityPlugin的行使:

    let networkPlugin = NetworkActivityPlugin { (type) in
    switch type {
    case .began:
        print("显示loading")
    case .ended:
        print("隐藏loading")
    }
}

一点差异也未有于在创造请求的Provider把它助长上去就能够

 let provider = RxMoyaProvider<APIManager>(plugins:[networkPlugin]) 

当然你也得以自定义一些功用的插件,只必要落成PluginType协议,具体职能落成可参看Moya暗许的插件:

final class CustomPlugin: PluginType {
  // MARK: Plugin
}

奥迪Q5x斯维夫特+Moya+ObjectMapper 网络请求与拍卖

 

 

安装接口的过期时间

诚如网络的请求要求依据现实的事情接口设置合适的过期时间,你能够参考一下形式开始展览安装

    let requestClosure = { (endpoint: Endpoint<T>, done: @escaping MoyaProvider<T>.RequestResultClosure) in
    guard var request = endpoint.urlRequest else { return }
    request.timeoutInterval = 30    //设置请求超时时间
    done(.success(request))
}

一如既往在创制请求的Provider把它助长上去就可以

let provider = RxMoyaProvider<APIManager>(requestClosure: requestClosure)

宗旨设置,RAV4xSift互联网请求管理。聊到底,那些设置最佳用一个 struct 去管理.

Example:

struct HttpArgument<T: TargetType> { 
    let endpointClosure = .....
    let requestClosure = ......
    let networkPlugin = ......
    let accessTokenPlugin = .....
}

利用的时候

   private lazy var provider: RxMoyaProvider = { () -> RxMoyaProvider<APIManager> in
    let argument = HttpArgument<APIManager>()
    let provider = RxMoyaProvider<APIManager>(endpointClosure: argument.endpointClosure,
                                            plugins:[argument.networkPlugin])

    return provider
}()
Moya轻便的介绍

Moya是一个基于Alamofire的Networking
library,并且增多了对于ReactiveCocoa和奥迪Q7xSwift的接口帮衬。

  接下去就介绍一下Moya的片段常见的用法:

  接下去就介绍一下Moya的一些大面积的用法:

Moya使用

1.第2需求经过枚举对请求实行分明分类

public enum XYJHomeRouter {
    /// 刷新首页
    case refreshHome(parameters: [String:Any])
    /// 获取bannar
    case getBannar(parameters: [String:Any])
}

二.让XYJHomeRouter枚举坚守TargetType协议,那一个Target就是你网络请求相关行为的定义,也得以自定义和谐,我们兑现那一个协议,也就约等于落成了网络请求必要的endpoint.
自定义的议和

public protocol XYJTargetType {
    var isShow: Bool { get }
}

XYJHomeRouter的实现

extension XYJHomeRouter: TargetType,XYJTargetType {

    public var baseURL: URL {
        return URL(string: baseHostString)!
    }

    public var path: String {
        switch self {
        case .refreshHome:
            return "yd/app/home"
        case .getBannar:
            return "yd/app/common/banners"
        }
    }
    public var method: Moya.Method {
        switch self {
        case .refreshHome:
            return .post
        case .getBannar:
            return .post
        }
    }
    public var parameters: [String: Any]? {
        switch self {
        case .refreshHome(parameters: let dict):
            return dict
        case .getBannar(parameters: let dict):
            return dict
        }
    }
    public var parameterEncoding: ParameterEncoding {
        return JSONEncoding.default
    }
    public var task: Task {
        return .request
    }

    public var validate: Bool {
        return false
    }
    //自己定义的协议实现,是否显示正在加载,有的接口在后台请求,不需要告诉用户
    public var isShow: Bool {
        switch self {
        case .refreshHome:
            return false
        case .getBannar:
            return false
        }
    }

三.在viewmodel中张开网络请求方法的包裹

  // 获取banner数据
    func getBanner(paramaters: [String: Any]) -> Observable<XYJResultList<XYJBanner>> {
        return XYJMoyaHttp<XYJHomeRouter>().sendRequest().request(.getBannar(parameters: paramaters)).mapObject(XYJResultList.self)
    }

咱俩看下XYJ莫亚Http<XYJHomeRouter>()的落成
参数:
EndpointClosure:能够对请求参数做特别的改换,如能够修改endpointByAddingParameters
endpointByAddingHTTPHeaderFields等
RequestClosure:你可以在出殡和埋葬请求前,做点手脚.决断有无网络做气泡提醒,修改超时时间,打字与印刷一些数额等
StubClosure:能够设置请求的延迟时间,能够作为模拟慢速网络
Manager:请求网络请求的格局。暗中认可是Alamofire
[PluginType]
:Moya提供了一个插件机制,使大家能够创立友好的插件类来做一些外加的业务。比方写Log,展现“黄花”等。抽离出Plugin层的目标,正是把和投机网络非亲非故的行事抽离。制止种种事务揉在同步不便于扩大

public class XYJMoyaHttp<T:TargetType> {
    func sendRequest() -> RxMoyaProvider<T> {
        return RxMoyaProvider<T>.init(endpointClosure: endpointClosure ,requestClosure: requestClosure,stubClosure: stubClosure,plugins: [NetworkLoggerPlugin.init(verbose: true,responseDataFormatter: {JSONResponseDataFormatter($0)}),spinerPlugin,XYJMoyaResponseNetPlugin()])
    }

    func sendUploadMultipart() -> RxMoyaProvider<T> {
        return RxMoyaProvider<T>.init(endpointClosure: endpointClosure ,requestClosure: requestClosure ,plugins: [NetworkLoggerPlugin.init(verbose: true,responseDataFormatter: {JSONResponseDataFormatter($0)}),spinerPlugin,XYJMoyaResponseNetPlugin()])
    }
    // MARK: - 设置请求头部信息
    let endpointClosure = { (target: T) -> Endpoint<T> in
        let url = target.baseURL.appendingPathComponent(target.path).absoluteString
        let endpoint = Endpoint<T>(
            url: url,
            sampleResponseClosure: { .networkResponse(200, target.sampleData) },
            method: target.method,
            parameters: target.parameters,
            parameterEncoding: target.parameterEncoding
        )
        //在这里设置你的HTTP头部信息
        return endpoint.adding(newHTTPHeaderFields: [

            :])
    }


    // 发请求之前判断是否有网络
    let requestClosure = { (endpoint: Endpoint<T>, done: MoyaProvider.RequestResultClosure) in
        if var request = endpoint.urlRequest {
            if(XYJNetworkMonitor.shareInstance.hasNetwork()) {
                done(Result.success(request))
            } else {
                done(Result.failure(MoyaError.requestMapping(noNetWorkTipsString)))
            }
        }
    }

    /// 单元测试代码
    let stubClosure: (_ type: T) -> Moya.StubBehavior  = { type1 in
        return StubBehavior.never
    }

}

/// 日志
///
/// - Parameter data: data数据
/// - Returns: Data数据类型
private func JSONResponseDataFormatter(_ data: Data) -> Data {
    do {

        let dataAsJSON = try JSONSerialization.jsonObject(with: data)
        let prettyData =  try JSONSerialization.data(withJSONObject: dataAsJSON, options: .prettyPrinted)
        return prettyData
    } catch {
        return data // fallback to original data if it can't be serialized.
    }
}

/// 指示灯的配置的初始化
let spinerPlugin = XYJNetworkActivityPlugin { state in
    guard let currentView = XYJLogVC.instance.currentVC?.view else {
        return
    }
    if state == .began {
        XYJProgressHUD.hide(view: currentView)//失把指示灯关掉,再显示
        XYJProgressHUD.showAdded(view: currentView)
    } else {
        XYJProgressHUD.hide(view: currentView)
    }
}

class XYJLogVC {
    var currentVC: UIViewController?
    //声明一个单例对象
    static let instance = XYJLogVC()
    private init() {}
}

public protocol XYJTargetType {

    var isShow: Bool { get }
}

(壹)依照作业须要创制具体请求:

(一)依照作业须要成立具体请求:

网络请求reposne的管理插件

能够依赖再次回到响应的状态码剖断业务成功恐怕退步,还是能再那里开展有个别特殊状态码的大局逻辑业务管理,比方有些状态码,要拓展弹出登入管理等

/// reposne的处理(net)
public final class XYJMoyaResponseNetPlugin: PluginType {
    /// 成功的状态码
    let normalCode =  ["0","0000"]
    //// 修改response的值
    public func process(_ result: Result<Moya.Response, MoyaError>, target: TargetType) -> Result<Moya.Response, MoyaError> {
        var result = result
        //JSONSerialization
        if case .success(let response) = result {
            let processedResponse = Response(statusCode: -1, data: response.data, request: response.request, response: response.response)
            guard let json = try? JSONSerialization.jsonObject(with: response.data, options: .allowFragments) as? [String:Any] , let code = json?["code"] as? String else {
                   return .failure(.jsonMapping(processedResponse))
            }
        if( !normalCode.contains(code) ) {  //业务失败
                if code == "C0001" {
                  //清理缓存,弹出登录框的逻辑
                }
                result = .failure(.statusCode(processedResponse)) 
            } else {   //业务成功
                let data = json?["data"]
                if let jsonDatas = data as? Data {
                    guard  let jsonData = try? JSONSerialization.data(withJSONObject: jsonDatas, options: []) else {
                        return .failure(.jsonMapping(processedResponse))
                    }
                    result = .success(Response(statusCode: -1, data: jsonData, request: response.request, response: response.response))
                } else {
                    result = .success(Response(statusCode: -1, data: response.data, request: response.request, response: response.response))
                }
            }
        }
        return result
    }

四.在调节器中进行调用

  vm.getBanner(paramaters: paras as! [String : Any]).asObservable().subscribe(onNext: { (result) in
            guard let bannars = result.data else {
                return
            }
            self.vm.cacheBanner(datas: bannars)
            self.bannerView.datas = bannars
        }, onError: { (_) in
            XYJLog(message: "获取bannar数据失败")
        }).disposed(by: self.disposeBag)

  打举例现在大家须要书写账户的有关接口,如Login、userInfo。那么首先我们得创制AccountService:

  打比近年来后我们供给书写账户的连锁接口,如Login、userInfo。那么首先咱们得创设Account瑟维斯:

JSON解析

咱俩得以独自新建八个文书,用来对莫亚的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))
        }
    }
enum AccountService {
    case login(phoneNum: NSInteger,passWord: NSInteger)
    case logout
}
enum AccountService {
    case login(phoneNum: NSInteger,passWord: NSInteger)
    case logout
}

ObjectMapper

ObjectMapper是用斯维夫特语言达成目的和JSON相互调换的框架,自定义的model要求贯彻Mappable协议,ObjectMapper能够很好的拍卖泛型类型的数目,但是那么些泛型需求贯彻Mappable协议,也得以管理好嵌套的数据结构
上面大家看下具体的利用
原本数据

{
    "code": "0",
    "data": {
        "expected_credit": "0",
        "noread_msg": "4",
        "role_type": "1",
        "total_credit": "0",
        "nick_name": "哦哦哦",
        "wait_bill": "1",
        "total_bill": "6"
    },
    "message": "成功"
}

数据模型管理

/// 返回结果模型
//T为泛型,遵循Mappable协议
class XYJResult<T: Mappable>: Mappable {
    var code: String?
    var message: String?
    var data: T?

    required init?(map: Map) {
    }
    init() {
    }

    func mapping(map: Map) {
        code <- map["code"]
        message <- map["message"]
        data <- map["data"]
    }
}


import UIKit
import ObjectMapper
class XYJHomeModel: Mappable {
    var nickName: String?
    var noReadMsg: String?
    var expectedCred: String?
    var totalBill: String?
    var totalCredit: String?
    var waitBill: String?
    var monthBill: String?
    //必须要实现的方法
    required init?(map: Map) {
    }
    //手动创建model时要写
    init() {}
   //建立映射关系--
    func mapping(map: Map) {
        nickName <- map["nick_name"]
        noReadMsg <- map["noread_msg"]
        expectedCred <- map["expected_credit"]
        totalBill <- map["total_bill"]
        totalCredit <- map["total_credit"]
        monthBill <- map["month_bill"]
        waitBill <- map["wait_bill"]
    }
}

参考资料:
https://github.com/Hearst-DD/ObjectMapper
http://www.codertian.com/2017/02/04/iOS-Moya-RxSwift-better-networking/

  然后让AccountService达成TargetType协议,定义请求需求的骨干新闻:

  然后让AccountService实现TargetType协议,定义请求必要的大旨音讯:

extension AccountService: TargetType {
    var baseURL: URL {
        return URL(string: ServiceBaseURL)!
    }

    var path: String {
        switch self {
        case .login(_, _):
            return "accountService/login"
        case .logout:
            return "accountService/logout"
        }
    }

    var method: Moya.Method {
        switch self {
        case .login(_, _):
            return .post
        case .logout:
            return .get
        }
    }

    var parameters: [String: Any]? {
        switch self {
        case .login(let phoneNum, let passWord):
            return ["phoneNum": phoneNum, "passWord": passWord]
        case .logout:
            return nil
        }
    }

    var parameterEncoding: ParameterEncoding {
        return JSONEncoding.default // Send parameters as JSON in request body
    }

    var sampleData: Data {
        return "".data(using: .utf8)!
    }

    var task: Task {
        return .request
    }

}
extension AccountService: TargetType {
    var baseURL: URL {
        return URL(string: ServiceBaseURL)!
    }

    var path: String {
        switch self {
        case .login(_, _):
            return "accountService/login"
        case .logout:
            return "accountService/logout"
        }
    }

    var method: Moya.Method {
        switch self {
        case .login(_, _):
            return .post
        case .logout:
            return .get
        }
    }

    var parameters: [String: Any]? {
        switch self {
        case .login(let phoneNum, let passWord):
            return ["phoneNum": phoneNum, "passWord": passWord]
        case .logout:
            return nil
        }
    }

    var parameterEncoding: ParameterEncoding {
        return JSONEncoding.default // Send parameters as JSON in request body
    }

    var sampleData: Data {
        return "".data(using: .utf8)!
    }

    var task: Task {
        return .request
    }

}

  如上大家就已经到位了网络请求所要求的2个endpoint。接着通过Moya提供3个发送请求的Provider就完成了基本的使用:

  如上我们就曾经形成了网络请求所急需的一个endpoint。接着通过Moya提供二个出殡和埋葬请求的Provider就完成了基本的使用:

let provider = MoyaProvider<AccountService>()

provider.request(.login(phoneNum: 12345678901, passWord: 123456)) { result in

            switch result {
            case let .success(response):
                //...............
                break
            case let .failure(error):
                //...............
                break
            }
        }
let provider = MoyaProvider<AccountService>()

provider.request(.login(phoneNum: 12345678901, passWord: 123456)) { result in

            switch result {
            case let .success(response):
                //...............
                break
            case let .failure(error):
                //...............
                break
            }
        }

(二)通过HTTPHeader设置公共请求参数

(二)通过HTTPHeader设置公共请求参数

  在其实费用中大家兴许会需求在呼吁头内增添一些集体请求参数,如用于识别部分阳台标识、辨别接口的版本号。你能够定义二个Endpoint的闭包,

  在实际上开采中我们或者会供给在呼吁头内增多一些共用请求参数,如用于识别部分平台标识、辨别接口的版本号。你能够定义3个Endpoint的闭包,

let publicParamEndpointClosure = { (target: AccountService) -> Endpoint<AccountService> in
            let url = target.baseURL.appendingPathComponent(target.path).absoluteString
            let endpoint = Endpoint<AccountService>(url: url, sampleResponseClosure: { .networkResponse(200, target.sampleData) }, method: target.method, parameters: target.parameters, parameterEncoding: target.parameterEncoding)
            return endpoint.adding(newHTTPHeaderFields: ["x-platform" : "iOS", "x-interface-version" : "1.0"])
        }
let publicParamEndpointClosure = { (target: AccountService) -> Endpoint<AccountService> in
            let url = target.baseURL.appendingPathComponent(target.path).absoluteString
            let endpoint = Endpoint<AccountService>(url: url, sampleResponseClosure: { .networkResponse(200, target.sampleData) }, method: target.method, parameters: target.parameters, parameterEncoding: target.parameterEncoding)
            return endpoint.adding(newHTTPHeaderFields: ["x-platform" : "iOS", "x-interface-version" : "1.0"])
        }

  然后在开创请求的Provider把它添加上去,

  然后在创制请求的Provider把它添加上去,

let provider = MoyaProvider(endpointClosure: publicParamEndpointClosure)
let provider = MoyaProvider(endpointClosure: publicParamEndpointClosure)

(三)通过插件的措施监听网络状态

(3)通过插件的格局监听网络状态

  平时大家会在开展网络请求的时候举办一些景色呈现,如loading,那么你能够通过插件的秘诀来达成。Moya暗中认可有四个插件:

  日常我们会在实行互联网请求的时候举香港行政局部气象彰显,如loading,那么您能够通过插件的办法来贯彻。Moya私下认可有五个插件:

  • AccessTokenPlugin 管理AccessToken的插件
  • CredentialsPlugin 管理认证的插件
  • NetworkActivityPlugin 管理网络状态的插件
  • NetworkLoggerPlugin 处理网络log的插件
  • AccessTokenPlugin 管理AccessToken的插件
  • CredentialsPlugin 管理认证的插件
  • NetworkActivityPlugin 管理网络状态的插件
  • NetworkLoggerPlugin 处理互连网log的插件

  在此间就演示一下NetworkActivityPlugin的运用:

  在那边就演示一下NetworkActivityPlugin的使用:

let networkPlugin = NetworkActivityPlugin { (type) in
            switch type {
            case .began:
                NSLog("显示loading")
            case .ended:
                NSLog("隐藏loading")
            }
        }
let networkPlugin = NetworkActivityPlugin { (type) in
            switch type {
            case .began:
                NSLog("显示loading")
            case .ended:
                NSLog("隐藏loading")
            }
        }

  同样在开立请求的Provider把它添加上去即可

  同样在开创请求的Provider把它添加上去即可

let provider = MoyaProvider<AccountService>(plugins: [networkPlugin])
let provider = MoyaProvider<AccountService>(plugins: [networkPlugin])

澳门葡京备用网址 ,  当然你也能够自定义一些效应的插件,只供给贯彻PluginType协议,具体效果落成可参考Moya暗中同意的插件:

  当然你也能够自定义一些成效的插件,只须要贯彻PluginType协议,具体功效达成可参考Moya暗许的插件:

final class CustomPlugin: PluginType {

    // MARK: Plugin

}
final class CustomPlugin: PluginType {

    // MARK: Plugin

}

(肆)设置接口的过期时间

(四)设置接口的晚点时间

  一般互连网的哀告必要依据实际的作业接口设置合适的超时时间,你能够参照一下主意举行安装,

  一般网络的伸手供给依照实际的作业接口设置合适的逾期时间,你能够参考一下主意开始展览设置,

let requestTimeoutClosure = { (endpoint: Endpoint<AccountService>, done: @escaping MoyaProvider<AccountService>.RequestResultClosure) in

            guard var request = endpoint.urlRequest else { return }

            request.timeoutInterval = 30    //设置请求超时时间
            done(.success(request))
        }
let requestTimeoutClosure = { (endpoint: Endpoint<AccountService>, done: @escaping MoyaProvider<AccountService>.RequestResultClosure) in

            guard var request = endpoint.urlRequest else { return }

            request.timeoutInterval = 30    //设置请求超时时间
            done(.success(request))
        }

  同样在开立请求的Provider把它添加上去即可

  同样在开创请求的Provider把它添加上去即可

let provider = MoyaProvider<AccountService>(requestClosure: requestTimeoutClosure)
let provider = MoyaProvider<AccountService>(requestClosure: requestTimeoutClosure)

  至此,使用Moya进行网络请求的着力用法已经介绍完了,首要是记录一下只是药厂,当然也盼望能对大家不怎么用处,多谢!

  至此,使用Moya实行互连网请求的着力用法已经介绍完了,主若是记录一下只是药市,当然也但愿能对大家某个用处,多谢!

资料参考:

资料参考:

 

 

相关文章

发表评论

电子邮件地址不会被公开。 必填项已用*标注

*
*
Website