Swift网络请求之Moya的使用

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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,117评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,328评论 1 293
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,839评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,007评论 0 206
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,384评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,629评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,880评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,593评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,313评论 1 243
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,575评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,066评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,392评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,052评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,082评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,844评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,662评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,575评论 2 270

推荐阅读更多精彩内容

  • 作为一个前端程序猿,下面这些站会让你眼前一亮。 amazeui框架组建丰富 http://amazeui.org...
    欧巴冰冰阅读 8,670评论 18 302
  • 阳春三月,好时光~ 还是这么忙碌,还是这么快节奏。沟通客户,跟进生产,优化产品。最近被产品搞得头都大了,高清的百多...
    昕栖息的小屋阅读 209评论 0 0
  • 很多人有时会想,为什么我上了大学选择了一个专业以后,这个专业就一定成为我的事业,我的职业以至于我未来人生的一个...
    山东水利职业学院专题阅读 313评论 0 0
  • 北方的冬天是让人喜欢也让人着迷的。寒冷的温度逐渐的冷却了我们内心的膨胀和躁动,慢慢的让大地变得肃杀了无生机。在这样...
    营州布衣阅读 354评论 4 7
  • 想把这里当成梦想开启的地方,我想要更好的自己,确一直害怕过程很辛苦,想一万件事,不去自己踏踏实实做好一件事,...
    彷徨的一小只阅读 116评论 0 0