封装一个 Swift-Style 的网络模块

Swift 跟 OC 有着完全不同的设计哲学,它鼓励你使用 protocol 而不是 super class,使用 enum 和 struct 而不是 class,它支持函数式特性、范型和类型推导,让你可以轻松封装异步过程,用链式调用避免 callback hell。如果你还是用 OC 的思维写着 Swift 代码,那可以说是一种极大的资源浪费,你可能还会因为 Swift 弱鸡的反射而对它感到不满,毕竟 Swift 在强类型和安全性方面下足了功夫,如果不使用 OC 的 runtime,在动态性方面是远不如 OC 的。

OOP 和消息传递非常适合 UI 编程,在这方面来说 OC 是非常称职的,整个 Cocoa Touch 框架也都是面向对象的,所以对于 iOS 开发来说,不管你使用什么语言,都必须熟悉 OOP。在 UI 构建方面,无论是 Swift 还是 OC,无非都是调用 API 罢了,在有自动提示的情况下,其实编码体验都差不多。那 Swift 相比于 OC 的优势到底体现在什么地方呢,我认为是 UI 以外的地方,跟 UI 关系越小,Swift 能一展拳脚的余地就越大,譬如网络层。

讲到网络层就绕不开 Alamofire,Alamofire 几乎是现在用 Swift 开发 iOS App 的标配,它是个很棒的库,几乎能满足所有网络方面的日常需求,但如果对它再封装一下的话,不仅使用起来更得心应手,而且能将第三方库与业务代码解耦,以后万一要更换方案会更加方便。

Alamofire 使用 Result 来表示请求返回的结果,它是个 enum,长这样:

我们可以对它进行扩展,让它支持链式调用:

有了这个扩展我们就可以定义一个parseResult的方法,对返回结果进行处理,像这样:

checkJSONDict用来处理服务器返回的错误信息,具体的处理逻辑不同项目都不一样,主要看跟服务器的约定,我就不细说了。valueForKey是对Dictionary的扩展,可以通过字符串拿到返回的 JSON 数据中需要的部分(先转换成[String: AnyObject]),支持用”.”分隔 key,从而取得嵌套对象。譬如这样一个东西:

你可以用"key2.nest"拿到value2,用"key3.nest1.nest2"拿到value3。我用reduce实现了这个功能:

有了parseResult之后,我们就可以轻松封装请求过程了:

API是一个枚举,有一个url的计算属性,用来返回 API 地址,configParameters用来配置请求参数,也跟具体项目有关,就不展开了,method可以设置一个项目中常用的 HTTP Method 作为默认参数。这个方法会返回一个Cancellable,长这样:

Request本来就实现了cancel方法,所以只要显式地声明一下它遵守Cancellable协议就行了,使用的时候像这样:

在请求完成之前,随时可以调用task?.cancel() 来取消这个网络任务。

当然如果你想在网络模块中把 JSON 直接转化成 Model 也是可以的,我个人倾向于使用 ObjectMapper 来构建网络 Model 层,于是就可以对外提供两个直接取得 Model 和 Model 数组的方法:

=>是我自定义的操作符,它有两个重载版本,都满足flatMap的参数要求:

于是就可以在业务代码中直接这样:

到此一个简洁方便的网络模块就差不多成型了,别忘了为你的模块添加单元测试,这会让模块的使用者对你的代码更有信心,而且在测试过程中会让你发现一些开发过程中的思维盲区,还能帮你优化设计,毕竟良好的可测试性在某种程度上就意味着良好的可读性和可维护性。

有什么建议欢迎在评论中指出 ^ ^

1 2 收藏 评论

相关文章

可能感兴趣的话题



直接登录
跳到底部
返回顶部