美文网首页
Swift网络请求之Moya的使用

Swift网络请求之Moya的使用

作者: keking | 来源:发表于2017-11-30 14:27 被阅读0次

    1,Alamofire网络框架请求数据
    在iOS的工程中,之前用的是Alamofire网络框架,这个框架的一个网络请求示例如下:

    func setUserStatus() {
        let parameters:[String : Any] = ["userid": userid!]
        Alamofire.request(URL_SET_USER_STATUS, method: .post, parameters: parameters, encoding: URLEncoding.default, headers: nil).responseObject{[weak self]
            (response :DataResponse<StatusModel>) in
            if self == nil{
                return
            }
            let ret = response.result.value
            if response.result.error != nil{
                ......
            }else{
                .......
            }
        }
    }
    

    每个接口都需要拼接这些信息,包括api路径,请求的方式,参数,参数编码格式,消息头等几个主要部分,获取到网络数据后,再解析数据进行处理。
    2,moya
    moya的中文说明:https://github.com/Moya/Moya/blob/master/Readme_CN.md
    它对网络请求的url和parameter进行了更深的封装
    TargetType这个是使用moya必须要实现的一个协议,这个里面我们基本可以看到它封装的主要内容

    public protocol TargetType {
    
        /// The target's base `URL`.
        var baseURL: URL { get }
    
        /// The path to be appended to `baseURL` to form the full `URL`.
        var path: String { get }
    
        /// The HTTP method used in the request.
        var method: Moya.Method { get }
    
        /// Provides stub data for use in testing.这个数据是用在api测试时用的
        var sampleData: Data { get }
    
        /// The type of HTTP task to be performed.
        var task: Task { get }
    
        /// Whether or not to perform Alamofire validation. Defaults to `false`.
        var validate: Bool { get }
    
        /// The headers to be used in the request.
        var headers: [String: String]? { get }
    }
    

    3,moya的使用示例
    基本的使用示例:https://github.com/Moya/Moya/blob/master/docs/Examples/Basic.md
    同样的接口封装成moya后

    //Moya 10的版本已经去掉了RxMoyaProvider代码,直接用MoyaProvider
    let provider = MoyaProvider<MyService>()
    provider.rx.request(.setUserStatus)
                .asObservable().mapJSON()
                .mapObject(type: UserStatusModel.self)
                .subscribe { [weak self] event in
                    if self == nil{
                        return
                    }
                    switch event {
                    case let .next(response):
                        //............
                        break
                    case let .error(error):
                        print(error)
                        //这个地方,处了网络异常外,对错误码也可处理
                        if let err = error as? NSError{
                            if err.domain == "Network"{
                                switch err.code{
                                case 401:
                                print("param invalide")
                                break
                                default:
                                print("other error")    
                                }
                            }else{
                                print("other error") 
                            }
                        }else{
                            print("other error") 
                        }
                        break
                    default:
                        break
                    }
                }.disposed(by: disposeBag)
    

    4,ObjectMapper
    获取到网络数据后,需要将json解析成对象数据,可配合ObjectMapper一起用。一般服务端返回的数据是

    {
    "code": 200,
    "message": "",
    "data": {}
    }
    

    这样我们可以对这些错误码进行统一处理,data数据解析成功后返回

    import Foundation
    import RxSwift
    import ObjectMapper
    import RxCocoa
    
    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
                }
                guard (dict["code"] as? Int) != nil else{
                    throw RxSwiftMoyaError.ParseJSONError
                }
                
                if let error = self.parseError(response: dict) {
                    throw error
                }
                return Mapper<T>().map(JSON: dict["data"] as! [String : Any])!
            }
        }
        
        func mapArray<T: Mappable>(type: T.Type) -> Observable<[T]> {
            return self.map { response in
                guard response is [Any] else {
                    throw RxSwiftMoyaError.ParseJSONError
                }
                
                guard let dicts = response as? [String: Any] else {
                    throw RxSwiftMoyaError.ParseJSONError
                }
                
                guard (dicts["code"] as?Int) != nil else{
                    throw RxSwiftMoyaError.ParseJSONError
                }
                
                if let error = self.parseError(response: dicts) {
                    throw error
                }
                
                return Mapper<T>().mapArray(JSONArray: [dicts["data"] as! [String : Any]])
            }
        }
        
        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
            }
            
        }
        
    //最外层的dictionary解析,将data数据取去后转换成json对象
    //如果是错误码,抛异常处理
        fileprivate func parseError(response: [String: Any]?) -> NSError? {
            var error: NSError?
            if let value = response {
                var code:Int?
                if let codes = value["code"] as? Int{
                    code = codes
                }
                if  code != 200 {
                    var msg = ""
                    if let message = value["message"] as? String {
                        msg = message
                    }
                    error = NSError(domain: "Network", code: code!, userInfo: [NSLocalizedDescriptionKey: msg])
                }
            }
            return error
        }
    }
    
    enum RxSwiftMoyaError: String {
        case ParseJSONError
    }
    
    extension RxSwiftMoyaError: Error {
        
    }
    

    至此,rxswift + moya就可以正常使用了
    当然,moya的相比alamofire还有很多好用的功能,后面再跟大家分享

    参考文档:
    http://www.jianshu.com/p/c1494681400b

    相关文章

      网友评论

          本文标题:Swift网络请求之Moya的使用

          本文链接:https://www.haomeiwen.com/subject/wcyvbxtx.html