Alamofire设计之道
1.初识
Swift编写的iOS App的网络模块都是基于Alamofire。Alamofire就是建立在NSURLSession上的封装。NSURLSession是在2013年推出的新API,并且Apple在2015年废弃了NSURLConnection。如果你的App还在用以NSURLConnection建立的网络层(比如AFNetworking 2.x),那么你真的应该考虑升级到NSURLSession(比如AFNetworking 3.x),废弃的API也许还能正常工作,但是Apple已对其不再维护,当然也就不支持HTTP 2.0等新特性。
2.我们来对比一下,同样GET一个URL,然后把数据解析成JSON。
使用NSURLSession层次的API如下
guard let url = URL(string:"https://raw.githubusercontent.com/LeoMobileDeveloper/ReactNativeFiles/master/person.json") else{return;} letdataTask= URLSession.shared.dataTask(with: url) { (data, response, error) in guard let data =data else{return; }do{let json=try JSONSerialization.jsonObject(with:data, options:.allowFragments) print(json) }catch let error{ print(error) }};dataTask.resume()
使用Alamofire
Alamofire.request("https://raw.githubusercontent.com/LeoMobileDeveloper/React-Native-Files/master/person.json").responseJSON { (response) in if let JSON = response.result.value {
print("JSON: \(JSON)")
}
}
可以看到,使用系统的API,我们不得不先创建URL,然后建立DataTask,并且Resume。接着在callback里去解析JSON。由于Swift是一种强类型的语言,我们不得不进行大量的逻辑判断和try-catch。
而Alamofire把这些步骤简化成了一个静态的方法调用,并且用链式的方式来处理异步的Response解析。由于是链式的,你可以用链式的方式实现很多逻辑,比如验证返回值:
Alamofire.request("https://httpbin.org/get")
.validate(statusCode: 200..<300) //返回值验证
.responseData { response in //解析返回的数据
switch response.result {
case .success:
print("Validation Successful")
case .failure(let error):
print(error)
}
}
链式的异步处理有很多优点:
优雅的处理大量的callback
代码更容易理解,更容易维护
不需要在每一步都进行错误检查
3.继承
NRULSessionTask是由继承来实现的,继承关系如下
URLSessionTask — Task的基类
URLSessionDataTask - 拉取URL的内容NSData
URLSessionUploadTask — 上传数据到URL,并且返回是NSData
URLSessionDownloadTask - 下载URL的内容到文件
URLSessionStreamTask — 建立TCP/IP连接
仿照这种关系,Alamofire的Request也是类似的继承关系:
Request — Task的基类
DataRequest - 拉取URL的内容NSData
UploadRequest — 上传数据到URL,并且返回是NSData
DownloadRequest - 下载URL的内容到文件
StreamRequest — 建立TCP/IP连接
其实原因和很简单:父类提供基础的属性和方法来给子类复用。
在Request中,除了继承,还使用了聚类的方式:由父类提供接口,初始化子类
4.协议
Swift是面向协议编程的语言。
Alamofire 大量使用了协议和代理。
Alamofire是一个优雅的Swift开源库,它的代码真的很优雅,强烈建议对Swift感兴趣并且想深入学习的同学用几天的空余时间去研究下。看的时候多问自己几个问题:
为什么这里要用protocol而不用继承?
为什么这里要用struct而不用class?
…..
总之,多问为什么,然后找到答案,就会很有收获。
下一篇介绍一下Moya的设计之道