RxSwift学习-- 网络层的搭建

作者: 奇董 | 来源:发表于2017-07-21 16:35 被阅读114次

我们平常的网络请求基本步骤
1 发送Request
2 接受 Response
3 jsonmodel (我目前是有这一步的)

1 不利用三方框架的Rx网络层

在实际生产过程中,我们都会使用第三方的网络框架。但为了学习基本流程,我们最好还是实现自己的一套简易框架。

1.1 对URLSession 进行Rx扩展,让他用它Rx的功能

创建URLSession+Rx文件

func response(request: URLRequest) -> Observable<(HTTPURLResponse, Data)> {
        return Observable.create { observable in
            let task = self.base.dataTask(with: request) { (data, response, error) in
                //处理数据
                if let error = error {
                    observable.onError(error)
                    return
                }

                observable.onNext((response as! HTTPURLResponse, data!))
                observable.onCompleted()
            }
            task.resume()
            return Disposables.create(with: task.cancel)
        }
    }

我们拆分来看一下

func response(request: URLRequest) -> Observable<(HTTPURLResponse, Data)> {
        return Observable.create { observable in
      //请求
            return Disposables.create()
        }
    }

这几乎是rx扩展的基本样式,中间加上URLSesson的请求 和 请求之后发送 错误 或者完成信号就可以了。
我们来看一下成果

let request = URLRequest.init(url: URL.init(string: "")!)
let response = URLSession.shared.rx.response(request: request)

response.subscribe(onNext: { (response, data) in
            //数据处理
 }).addDisposableTo(bag)

数据处理这部分也挺恶心了,也应该封装起来
通常数据处理 我们先处理data -> json ,之后json ->model. 事实上 不是所有的VC需要的数据都是model.所以 我们要暴露json 和model 2个接口。供调用者选用

在处理数据之前要确定数据是否有效,根据返回的状态码来判断,
筛选出正常返回的数据

func data(request: URLRequest) -> Observable<Data> {
        return response(request: request).map { (response, data) in
            if 200..<300 ~= response.statusCode {
                return data
            } else {
                throw URLSessionError.failed
            }

        }
    }

json

func json(request: URLRequest) -> Observable<[String: Any]> {
        return data(request: request).map{ data  in
            let json = try JSONSerialization.jsonObject(with: data, options: .allowFragments) as? [String: Any]

            return json!
        }
    }

model
转化model 这一步 这里我没有自己用原生实现,Swift不支持运行时(不包含继承NSObject的类)这里偷偷的用一下三方吧ObjectMapper(用法 后面介绍)

func model<T: Mappable>(request: URLRequest, model: T.Type) -> Observable<T> {
        return json(request: request).map{ json in
            let object = Mapper<T>().map(JSONObject: json["data"])
            return object!
        }
    }

这里的转model 在实际情况下会出现许多问题。举个例子
商品列表 商品详情
商品详情是单纯的model
商品列表是 model的数组,所以根据不同情况可能还需要一个ModelArray的方法。和model的一样,就不在重复了。
我们到VM中看看我们的战果

let request = URLRequest.init(url: URL.init(string: "")!)
let response = URLSession.shared.rx.model(request: request, model: GoodsDetailModel.self)

response.subscribe(onNext: { model in
            //数据处理
        }).addDisposableTo(bag)

这样我们一个基本的rx 的网络层基本完成了。如果要使用可以放在一个NetWorkingService类 。避免于vm大量的耦合。具体封装方法 就看大家的想法啦。是集约型 还是 分散型,都看自己的喜好了

2 RxMoya

在生产中,强烈推荐RxMoya真的大而全。
这边我们简单的介绍使用方法
首先确定配置文件创建XXAPI.Swift
我随便写一个了

enum GoodsAPI {
    case goodsDetail(goodsID: String)
}

extension GoodsAPI: TargetType {
    var parameterEncoding: ParameterEncoding {
        return URLEncoding.default
    }

    var task: Task {
        return .request
    }

    var path: String {
        return ""
    }

    var base: String {
        return ""
    }

    var baseURL: URL {
        return URL.init(string: base)!
    }

    var parameters: [String: Any]? {
        switch self {
        case .goodsDetail(let id):
            return []
        default:
            return nil
        }
    }

    var method: Moya.Method {
        return .post
    }

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



}

遵循TargetType 实现基本配置
然后在VM中调用

let service = RxMoyaProvider<GoodsAPI>()

    var goodsDetailModel: Observable<GoodsDetailModel> {
        return self.service.request(.goodsDetail(goodsID: "10133")).mapObject(GoodsDetailModel.self)
    }

这样就可以让VM中的model暴露给VC使用了。简单方便

=========
介绍下ObjectMapper的使用
1 遵循 Mappable协议
2 实现协议方法 init 和 mapping
这里的mapping 一定要写映射关系,毕竟没有运行时这种东西了。
注意的是如果返回的Int类型,你用String 是无法接受的(很难受)

struct GoodsDetailModel: Mappable {
    var goodsID: Int?
    var goodsInfo: String?
    var goodsName: String?
    var introduction: String?
    var label: String?
    var tag: String?
    var goodsPic: String?
    var xPrice: String?
    var yPrice: String?
    var number: Int?
    var batchNO: String?
    var activityGoods: Bool?

    init?(map: Map) {

    }

    mutating func mapping(map: Map) {
        goodsID <- map["goodsID"]
        goodsInfo <- map["goodsInfo"]
        goodsName <- map["goodsName"]
        introduction <- map["introduction"]
        label <- map["label"]
        tag <- map["tag"]
        goodsPic <- map["goodsPic"]
        xPrice <- map["xPrice"]
        yPrice <- map["yPrice"]
        number <- map["number"]
        batchNO <- map["batchNO"]
        activityGoods <- map["activityGoods"]
    }

}

相关文章

网友评论

    本文标题:RxSwift学习-- 网络层的搭建

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