moya + RxSwift 进行网络请求
1.关于moya
如在OC中使用AFNetworking一般,Swift我们用Alamofire来做网络库.而Moya在Alamofire的基础上又封装了一层:
官方说moya
有以下特性(我也就信了):
- 编译时检查正确的API端点访问.
- 使你定义不同端点枚举值对应相应的用途更加明晰.
- 提高测试地位从而使单元测试更加容易.
2.开始
1.创建枚举API
就像这样:
enum APIManager {case getNewsLatest//获取最新消息case getStartImage// 启动界面图像获取case getVersion(String)//软件版本查询case getThemes//主题日报列表查看case getNewsDetail(Int)//获取新闻详情
}
2.实现TargetType
协议
就像这样:
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/" + versioncase .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
的扩展,具体说就是对于RxSwift
和ReactiveCocoa
的扩展,通过与这两个库的结合,能让Moya
变得更加强大。我选择RxSwift
的原因有两个,一个是RxSwift
的库相对来说比较轻量级,语法更新相对来说比较少,我之前用过ReactiveCocoa
,一些大版本的更新需求重写很多代码,第二个更重要的原因是因为RxSwift
背后有整个ReactiveX
的支持,里面包括Java
,JS
,.Net
, Swift
,Scala
,它们内部都用了ReactiveX
的逻辑思想,这意味着你一旦学会了其中的一个,以后可以很快的上手ReactiveX
中的其他语言。
Moya
提供了非常方面的RxSwift
扩展:
let provider = RxMoyaProvider<APIManager>()
provider.request(.getNewsLatest).filterSuccessfulStatusCodes().mapJSON().subscribe(onNext: { (json) in//do something with postsprint(json)}).addDisposableTo(disposeBag)
解释一下:
RxMoyaProvider
是MoyaProvider
的子类,是对RxSwift
的扩展filterSuccessfulStatusCodes()
是Moya
为RxSwift
提供的扩展方法,顾名思义,可以得到成功地网络请求,忽略其他的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) incompleted(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> inreturn 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)!}
}
5.配合ObjectMapper
毕竟将json数据转换成model的库那么多 ….,所以……,用哪个很随意…..这里再介绍一下ObjectMapper
1.创建model类
class DetailModel: Mappable {var body = String()var image_source: String?var title = String()var image: String?var share_url = String()var js = String()var recommenders = [[String: String]]()var ga_prefix = String()var section: DetailSectionModel?var type = Int()var id = Int()var css = [String]()func mapping(map: Map) {body <- map["body"]image_source <- map["image_source"]title <- map["title"]image <- map["image"]share_url <- map["share_url"]js <- map["js"]recommenders <- map["recommenders"]ga_prefix <- map["ga_prefix"]section <- map["section"]type <- map["type"]id <- map["id"]css <- map["css"]}required init?(map: Map) {}
}
使用 ObjectMapper
,需要让自己的 Model
类使用 Mappable
协议,这个协议包括两个方法:
required init?(map: Map) {}func mapping(map: Map) {}
在 mapping
方法中,用 <-
操作符来处理和映射你的 JSON
数据。
数据类建立好之后,我们还需要为 RxSwift
中的 Observable
写一个简单的扩展方法 mapObject
,利用我们写好的model
类,一步就把JSON
数据映射成一个个 model
。
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 errorguard let dict = response as? [String: Any] else {throw RxSwiftMoyaError.ParseJSONError}return Mapper<T>().map(JSON: dict)!}}func mapArray<T: Mappable>(type: T.Type) -> Observable<[T]> {return self.map { response in//if response is an array of dictionaries, then use ObjectMapper to map the dictionary//if not, throw an errorguard let array = response as? [Any] else {throw RxSwiftMoyaError.ParseJSONError}guard let dicts = array as? [[String: Any]] else {throw RxSwiftMoyaError.ParseJSONError}return Mapper<T>().mapArray(JSONArray: dicts)!}}
}enum RxSwiftMoyaError: String {case ParseJSONErrorcase OtherError
}extension RxSwiftMoyaError: Swift.Error { }
mapObject
方法处理单个对象,mapArray
方法处理对象数组。如果传进来的数据
response
是一个dictionary
,那么就利用ObjectMapper
的map
方法映射这些数据,这个方法会调用你之前在mapping
方法里面定义的逻辑。如果
response
不是一个dictionary
, 那么就抛出一个错误。在底部自定义了简单的
Error
,继承了Swift
的Error
类,在实际应用过程中可以根据需要提供自己想要的Error
。
然后运行请求方法:
class DetailViewModel {private let provider = RxMoyaProvider<APIManager>()func getNewsDetail(id: Int) -> Observable<DetailModel> {return provider.request(.getNewsDetail(id)).filterSuccessfulStatusCodes().mapJSON().mapObject(type: DetailModel.self)}
}
有没有感觉很爽呢!————源码地址,共同学习!
原文地址
有不对之处,,,,还望各路大神不吝指正!
moya + RxSwift 进行网络请求相关推荐
- 项目剖析03-swift 网络请求Moya+HandyJSON+RxSwift
项目第一版网络框架用的是siesta,它的缓存与自动刷新确实很好用而且代码很简洁,但是在文件的上传与下载以及对返回类型需要精确匹配要求这方面就很不友好,所以在第二版的我选择了Moya,它是一个网络抽象 ...
- iOS 【如何写出最简洁优雅的网络封装 Moya + RxSwift】
前言 Why Moya ? Alamofire可能是iOS Swift中最常用的HTTP networking library,用Alamofire可以抽象出NSURLSession和其中很多繁琐的细 ...
- Swift 网络请求 Moya+RxSwift
Swift中优雅的网络请求 官方github // 1.定一个enum enum MyService {xxxxcase showUser(id: Int)xxx }// 2.扩展这个enum,符合 ...
- 通过 Moya + RxSwift + Argo 完成网络请求
作者:@请叫我汪二 授权本站转载. 最近在新项目中尝试使用 Moya+RxSwift+Argo 进行网络请求和解析,感觉还阔以,再来给大家安利一波. Moya Moya 是一个基于 Alamofire ...
- Moya+RxSwift+HandyJson 实现网络请求及模型转换
CocoaPods集成 pod 'RxCocoa' pod 'RxSwift'pod 'Moya/RxSwift' pod 'HandyJSON' Moya简单使用 定义枚举,存储网络请求 // 1 ...
- Moya+ RxSwift+HandyJSON 优雅处理网络请求
前言 在移动端的开发中,网络请求是必不可少的.之前写过Alamofire的简单使用,但是一般开发中都会对这些第三库封装,然后使用,之前自己封装的demo也是借鉴了一些Moya的设计思路.今天就介绍一下 ...
- Swift 优雅的网络请求Moya
Moya使用demo Moya 面向协议 Moya的模块组成 代码demo Controller中使用 Moya Moya是一个网络抽象层,它在底层将Alamofire进行封装,对外提供更简洁的接口供 ...
- Swift 掌控Moya的网络请求、数据解析与缓存
Moya 在Swift开发中起着重要的网络交互作用,但是还有不如之处,比如网络不可用时,返回的 Response 为 nil,这时还得去解析相应的 Error Codable 可以帮助我们快速的解析数 ...
- rxswift 网络请求_使用RxSwift将身份验证请求链接到多个服务
rxswift 网络请求 At a company that I have worked in the past, a high-traffic online classifieds, the bac ...
- Swift 网络请求库Moya的使用
Moya是Swift中的网络库Alamofire的二次封装,Alamofire本身使用起来是很简单方便的,例子如下: func loadData(){var param = [String:Strin ...
最新文章
- SCLS:中科院遗传发育在拟南芥二半萜类化合物调控根系微生物组取得突破进展
- 冒泡排序讲的明白 也有代码的
- JavaWeb——通过Listener理解域对象生命周期
- 各纬度气候分布图_印度和中国都是季风气候显著的国家,但冬夏季风的强弱却完全不同...
- WPF 学习笔记 路由事件
- 高效管理http连接
- 计算机维护系统Win8PE,U盘启动计算机维护系统
- k2p华硕系统怎么设置_斐讯K2刷华硕固件教程
- WiFi路由器的速度到底怎么算的?
- 波士顿学院计算机,波士顿学院(Boston College)_快飞留学
- ERROR ~/.vuerc may be outdated. Please delete it and re-run vue-cli in manual mode.
- Python-docx 读写 Word 文档:插入图片、表格,设置表格样式,章节,页眉页脚等
- 枚举报错 No enum constant XX 处理方法
- 职场社交赛道上,脉脉靠什么弯道超车
- 为什么 200M 宽带,打王者荣耀还是会有 460 的延迟?
- 2019年别离职、别创业、别投资,收藏好这些热点好好干!
- 知识星球爬虫2023-2-9
- 产业链图谱:2021年中国半导体产业链图谱|产业链全景图
- 阿里出品移动研发“神器” 阿里移动云系列第二篇|“移”步到位:一站式移动应用研发体系...
- 【答学员问】34岁想转行做it还可以吗?
热门文章
- spring boot中使用websocket实现点对点通信与服务器推送
- CSP模测(一)A卷
- sena utility Android apk,Sena 30K Utility
- 计算机专业的求职信英文版带翻译,[求职信英语作文带翻译]求职信的英语作文4篇...
- 基于STM32单片机的智能药盒带语音播报原理图程序
- 《月亮与六便士》的读后感作文3000字
- 台式计算机usb口不能用,电脑usb接口没反应是什么原因?电脑usb接口没反应解决方法...
- java tic tac toe_确定Tic Tac Toe游戏的算法
- 计算机不能关机处理方法,电脑不能关机怎么回事 电脑不能关机处理方法讲解...
- TDS:标签平台+API平台+数据共享平台,助力数据运营平台建设