Moya 与 RxSwift 使用

如在OC中使用AFNetworking通常,Swift咱们用Alamofire来作网络库.而Moya在Alamofire的基础上又封装了一层:
ios

1.关于moya

moyamoyagit

官方说moya有如下特性-_-:github

  • 编译时检查正确的API端点访问.
  • 使你定义不一样端点枚举值对应相应的用途更加明晰.
  • 提升测试地位从而使单元测试更加容易.

2.开始

1.建立枚举API

就像这样:json

enum APIManager {
case getNewsLatest//获取最新消息
case getStartImage// 启动界面图像获取
case getVersion(String)//软件版本查询
case getThemes//主题日报列表查看
case getNewsDetail(Int)//获取新闻详情
}

 

2.实现TargetType协议

就像这样:api

extension APIManager: TargetType {
 
/// The target's base `URL`.
var baseURL: URL {
 
return URL.init(string: "http://news-at.zhihu.com/api/")!
}
 
/// The path to be appended to `baseURL` to form the full `URL`.
var path: String {
 
switch self {
 
case .getNewsLatest:
return "4/news/latest"
 
case .getStartImage://start-image 后为图像分辨率,接受任意的 number*number 格式, number 为任意非负整数,返回值均相同。
return "4/start-image/1080*1776"
 
case .getVersion(let version)://URL 最后部分的数字表明所安装『知乎日报』的版本
return "4/version/ios/" + version
 
case .getThemes:
return "4/themes"
 
case .getNewsDetail(let id):
return "4/news/\(id)"
 
}
 
 
}
 
/// The HTTP method used in the request.
var method: Moya.Method {
 
return .get
}
 
/// The parameters to be incoded in the request.
var parameters: [String: Any]? {
 
return nil
}
 
/// The method used for parameter encoding.
var parameterEncoding: ParameterEncoding {
 
return URLEncoding.default
}
 
/// Provides stub data for use in testing.
var sampleData: Data {
 
return "".data(using: String.Encoding.utf8)!
}
 
/// The type of HTTP task to be performed.
var task: Task {
 
return .request
}
 
/// Whether or not to perform Alamofire validation. Defaults to `false`.
var validate: Bool {
 
return false
}
 
}

 

在这里,能够设置请求的参数,例如url……method……para等.网络

3.使用

Moya的使用很是简单,经过TargetType协议定义好每一个target以后,就能够直接使用Moya开始发送网络请求了。就像这样:闭包

let provider = MoyaProvider<APIManager>()
provider.request(.getNewsLatest) { result in
// do something with result
}

 

3.配合RxSwift

Moya自己已是一个使用起来很是方便,可以写出很是简洁优雅的代码的网络封装库,可是让Moya变得更增强大的缘由之一还由于它对于Functional Reactive Programming的扩展,具体说就是对于RxSwiftReactiveCocoa的扩展,经过与这两个库的结合,能让Moya变得更增强大。我选择RxSwift的缘由有两个,一个是RxSwift的库相对来讲比较轻量级,语法更新相对来讲比较少,我以前用过ReactiveCocoa,一些大版本的更新需求重写不少代码,第二个更重要的缘由是由于RxSwift背后有整个ReactiveX的支持,里面包括JavaJS.NetSwiftScala,它们内部都用了ReactiveX的逻辑思想,这意味着你一旦学会了其中的一个,之后能够很快的上手ReactiveX中的其余语言。app

Moya提供了很是方面的RxSwift扩展:ide

let provider = RxMoyaProvider<APIManager>()
provider.request(.getNewsLatest)
.filterSuccessfulStatusCodes()
.mapJSON()
.subscribe(onNext: { (json) in
//do something with posts
print(json)
})
.addDisposableTo(disposeBag)

 

解释一下:post

  • RxMoyaProviderMoyaProvider的子类,是对RxSwift的扩展

  • filterSuccessfulStatusCodes()MoyaRxSwift提供的扩展方法,顾名思义,能够获得成功地网络请求,忽略其余的

  • mapJSON()也是Moya RxSwift的扩展方法,能够把返回的数据解析成 JSON 格式

  • subscribe 是一个RxSwift的方法,对通过一层一层处理的 Observable 订阅一个 onNext 的 observer,一旦获得 JSON 格式的数据,就会经行相应的处理

  • addDisposableTo(disposeBag) 是 RxSwift 的一个自动内存处理机制,跟ARC有点相似,会自动清理不须要的对象。

4.配合HandyJSON

在实际应用过程当中网络请求每每紧密链接着数据层(Model),具体地说,在咱们的这个例子中,通常咱们须要创建一个类用来统一管理数据,而后把获得的 JSON 数据映射到数据层(Model)。

struct MenuModel: HandyJSON {
var others: [ThemeModel]?
 
}
 
struct ThemeModel: HandyJSON {
 
var color: String?
var thumbnail: String?
var id: Int?
var description: String?
var name: String?
}

 

而后建立ViewModel类,建立具体请求方法:

class MenuViewModel {
 
private let provider = RxMoyaProvider<APIManager>()
var dispose = DisposeBag()
 
func getThemes(completed: @escaping (_ menuModel: MenuModel) -> ()){
 
provider
.request(.getThemes)
.mapModel(MenuModel.self)
.subscribe(onNext: { (model) in
 
completed(model)
}, onError: { (error) in
 
}, onCompleted: nil, onDisposed: nil).addDisposableTo(dispose)
 
}
 
}

 

这里解释一下:
我这里是将请求的数据经过闭包传了出去,固然也能够不那么作.我的喜爱问题..

这里是为 RxSwift 中的 ObservableType和 Response写一个简单的扩展方法 mapModel,利用咱们写好的Model 类,一步就把JSON数据映射成 model

extension ObservableType where E == Response {
public func mapModel<T: HandyJSON>(_ type: T.Type) -> Observable<T> {
return flatMap { response -> Observable<T> in
return Observable.just(response.mapModel(T.self))
}
}
}
 
extension Response {
func mapModel<T: HandyJSON>(_ type: T.Type) -> T {
let jsonString = String.init(data: data, encoding: .utf8)
return JSONDeserializer<T>.deserializeFrom(json: jsonString)!
}
}

 

文章转载自  ,以作记录

相关文章
相关标签/搜索