Swift-自己封装一个网络请求,基于Rxswift、Moya、
2019-03-25 本文已影响17人
Fisland_枫
近来项目需求,需要用到了Rxswift和Moya,但是网上很多例子Moya都是基于Mapper封装,而Mapper的创建的代码实在有点多,而且Swift4.0新特性之一就是官方自己出的JSON解析-Codable,那么我们就用起来吧。
由于篇幅问题,Codable具体使用不在这里赘述
核心代码
主要是封装Moya的provider
/// 默认rx请求
///
/// - Parameters:
/// - api: api
/// - type: 解析类型
/// - Returns: 返回数据或错误
public static func rxRequest<T:Codable>(_ api :MultiTarget, type:T.Type) -> Single<T>{
let decoder = CleanJSONDecoder()
return self.provider.rx.request(api)
.asObservable()
.take(1)
.filterSuccess()
.map(type, using: decoder)
.observeOn(MainScheduler.instance)
.asSingle()
}
- 其中take(1)是保证该信号只执行一次,避免了多次请求的问题
- moya也对codable做了分装,需要调用其对应方法就可以
- filterSuccess,在这个方法中主要对错误进行统一处理,每个公司可能都每个公司自己的数据定义,这里也只是作为参考
public func filterSuccess() -> Observable<E> {
return flatMap { (response) -> Observable<E> in
let json = try JSON(response.mapJSON())
//这里的情况是,只有code为0的时候,数据data才有东西
if json.dictionaryValue["code"]?.intValue == 0{
//code为0,表示成功
return Observable.just(response)
}
//抛出错误
if let errormodel = try? JSONDecoder().decode(ErrorResponse.self, from: json.rawData()){
return Observable.error(HTTPServiceError.logic(err: errormodel))
}
return Observable.error(MoyaError.jsonMapping(response))
}
}
具体调用
//获取语言
let api = MultiTarget(TestAPI.language)
//返回的是信息流 Single的
JFHTTPService.rxRequest(api, type: Languages.self).subscribe(onSuccess: { (languages) in
print(languages)
}) { (error) in
}.disposed(by: rx.disposeBag)
//获取频道 channel
let doubanList = MultiTarget(DouBanAPI.channels)
JFHTTPService.rxRequestData(doubanList, with: "channels", type: [Channel].self).subscribe(onSuccess: { [weak self](list) in
guard let self = self else{ return }
self.dataSource = list
self.table.reloadData()
print(list)
}) { (error) in
}.disposed(by: rx.disposeBag)
- 其中api使用MultiTarget,这样可以项目内使用多个target达到组件化,不用所有的请求都在一个文件,GitHub demo中有具体使用
- 返回的是Single的流数据,可以对应该信号,再做别的操作,例如重试(retry)、合并(flatMap)、Map处理等等
- 传入的可以是该model的类型(model.self)或者是数组的类型([model].self)
举个例子
GitHub例子
Demo