大数据

Alamofire+RxSwift实现一个优雅的网络请求

在封装网络层的时候,首先瞥了一眼Alamofire,发现似乎一切都很不错并不用什么封装。。但是善于增加复杂度的我并不死心。于是就有了接下来的折(zhuang)腾(x)

为了响应swift面向协议编程的号召,在这里我定义了一个protocol,定义了请求路径,请求方式,参数,以及是否显示HUD

public protocol Request {

var path:String{get}

var method:HTTPMethod{get}

var parameters: [String:Any]? {get}

var hud:Bool{get}

}

得益于swift 3的花式语法,我们可以给这个protocol加一个默认实现。这样的好处就是负责实现这个协议的class,enum或是struc可以忽略协议扩展中已经实现的方法

extension Request{

var hud:Bool{

return false

}

var method:HTTPMethod{

return HTTPMethod.post

}

}

请求协议写完后,我们再来写一个请求方法,这里选择了struc作为NetworkClient

public struct NetworkClient{

static func send(_r:T) ->Observable<[String:Any]>

}

注意,这个方法里我们用了一波泛型,约束了参数r必须是实现了Requst协议

请求方法

同时这个方法还返回了一个约束数据类型为字典的Observable(在RAC里是RACSingal)。在这里我们默认了接口的是标准RESTAPI。所以我们可以分别处理code,message,result。

这里再贴一下我对error的处理

这里我们定义了一个实现Error协议的CZSError定义了几个简易的error,以及show方法

这样一个简易的网络请求框架就基本完成了。接下来我们以登陆作为🌰来看一下它是怎么工作的

首先新建一个LoginAPI.swift。在里面声明一个enum。里面有两个接口,登陆,获取短信验证码

enum LoginAPI {

case Login(mobile:String?, auth_code:String?)

case SmsCode(mobile:String?)

}

接下来我们让这个enum实现Request协议

看起来还不错,每一个请求都可以单独配置参数,请求地址,或是HUD,或者你能想到的任何东西!

ok,最后一步,发起请求,项目中使用的是MVVM架构,所以VC和ViewModel是双向绑定的

在viewmodel中LoginStatus,和signedIn的声明

viewModel

简单说一下信号之间的转换。loginTap产生的是一个Observable信号,把这个信号转换成了由phoneTextField和codeTextField(Observable)聚合所产生的信号,然后flatMap得到phone和code,同时需要return一个 Observable信号,但是我们的send函数返回的是Observable<[String:Any]>类型的信号,这里我们来一个map,把信号中的数据转成LoginStatus类型,同时也可以做一些额外的处理。

解释一下flatMap和map,前者是return的是一个信号,而后者则是return 信号中的数据。说人话。。如果把这个过程比作水在管道里流动的话,前者是换了一节管道,而后者则是换了管道中的水

最后,我们在controller中订阅这个信号,拿到处理好后的结果。

在viewController中订阅这个信号

一切都是辣么的完美。不是吗

Demo

(手机号输入00000000000验证失败,其他任意十一位数字都验证为成功)