Swift 轻量级网络层设计
来源:互联网 发布:淘宝店卖家开店时间 编辑:程序博客网 时间:2024/06/07 20:42
前言
普遍我们的网络层设计的时候直接是如下结构APIManager.post(url, parameter,completeHandle),服务器配置在APIManager.m文件中进行配置。这样一个简单便捷网络请求类便写好了,但细心思考我们会发现如下一些问题:
相同API可能分散各处导致每次需要填写的参数key值。回调处理代码也可能会存在冗余。
//例如登录功能 APIManager.post("登录APIUrl",{"name":"","pwd":""},completeHandle)//登录功能首先必然存在于LoginVc中LoginVC ==> 登录功能 //此时要求实现自动登录功能,那么在主控制器生成时应该判断是否可以自动登录(当然也可以推出LoginVc后再去自动登录)MainVc ==> 自动登录(登录功能)
此时便需要在两处来写入url、parameter及回调方法,当此接口有更新时就需要在两处进行修改,若工程中用到的此网络功能越多则需要修改的地方也越多!
部分网络请求需要随着页面的pop而取消,手动进行管理task显得笨拙而麻烦。
关于网络请求起飞后回调没有着陆点是很危险的一件事,因此正常的做法是让APIManager.post返回task任务,并有当前请求发起类持有,并在当前请求类析构并且task任务未完成时取消。这样的操作方式一看就繁琐,若一个大工程处处这样维护怕是相当麻烦了!
因此我们便需要设计出一个能解决上述问题的网络层设计
设计模式
此种设计主要是请求类持有自定义Request,并向中间件BQAPIManager传入Request调用URLSession。此过程中Request会持有task任务,当请求类被释放时,Request也会释放,此时判断其是否有任务执行如有任务执行则停止执行。从而达到自动取消任务的功能。而此时针对相同的url及其参数便可封装与一个Request中,可有效的减少冗余代码!
关键类说明
BQRequest.Swift
主要在于封装参数key值和设定url并处理网络请求类容及持有并按需取消或释放task任务
//关键代码如下 var method: HTTPMethod = .post var result: Any?//如成功处理网络请求内容后result有值 weak var task: URLSessionTask? public func url() -> String { return "" }//API接口 //模型转字典 public func toDiction() -> [String: Any] { let mir = Mirror(reflecting: self) var dict = [String: AnyObject]() for p in mir.children { if p.label == "method" || p.label == "result" || p.label == "task"{ continue } dict[p.label!] = (p.value as AnyObject) } return dict } //请求内容处理 public func responseAction(data: Data?, response: URLResponse?, error: Error?) { if let data = data { do { self.result = try JSONSerialization.jsonObject(with: data, options: .allowFragments) } catch let err as NSError { print(err.localizedDescription) } } if let error = error { print(error.localizedDescription) } } //保证析构时(请求类不存在时)取消正在执行的任务 deinit { if let task = self.task{ if task.state == .running || task.state == .suspended { print("cancel \(task)") task.cancel() } self.task = nil } }
BQAPIManager.Swift
主要作用为配置服务器环境(方便本地、测试服、正式服的切换),并通过传入的Request发起网络请求。
其中主要的关键点在与避免Request与task的循环持有。
//关键代码如下public class func sendRequest(request: BQRequest, completionHandler:@escaping () -> ()) { weak var req = request let task = BQNetWork.sendRequest(urlstr: baseUrl + request.url(), parameter: request.toDiction(), method: request.method, time: 10, headers: nil) { (data, response, error) in //对返回内容进行处理,如果处理成功结果赋予Request.result之中 req?.responseAction(data: data, response: response, error: error) DispatchQueue.main.async { if req?.task != nil { completionHandler() //任务完成后释放task任务 req?.result = nil//此处最好让网络调用类来决定是否置空result req?.task = nil } } } request.task = task }
其中BQNetWork中的内容是基于URLSession的一个简单封装,这里便不再详述
使用方式
以上述登录功能为示例,此时需设计LoginRequest继承与BQRequest并重写其url 及 responseAction方法
public name: String? public pwd: String? override public func url() -> String { return "登录APIUrl" } override public func responseAction(data: Data?, response: URLResponse?, error: Error?) { super.responseAction(data: data, response: response, error:error); if let result = self.result { //登录处理通用功能实现 } }
接着让LoginVc持有LoginRequest对name及pwd赋值(减少因参数key字段出错而失败的情况),并通过BQAPIManager发起请求即可。
- Swift 轻量级网络层设计
- Android网络层与数据层设计
- iOS网络层设计感想
- iOS网络层设计感想
- iOS网络层设计感想
- iOS网络层设计感想
- 轻量级网络
- swift 面向协议的网络框架设计
- 移动游戏的网络通信层设计
- iOS网络层架构设计分享
- iOS网络层架构设计1
- iOS网络层架构设计分享
- AndroidApp应用中的网络层设计
- 3D游戏中的网络层设计
- 对AF的二次封装--ELNetworking(一个轻量级的iOS网络层)
- Swift 轻量级的键盘管理器
- 网络五子棋的架构设计(一)--网络通信层
- 轻量级多线程网络爬虫
- jquery切换div,打开关闭按钮
- 网站中取访问用户真实ip地址
- CCF之模板生成
- linux iostat命令
- @Override 的作用
- Swift 轻量级网络层设计
- eclipse的log信息一闪而过
- webpack使用file-loader单独打包js文件
- Windows 下安装Go
- svn服务管理脚本
- 【MyBatis学习14】MyBatis和Spring整合
- keil 环境下的MicroLIB 简介和使用
- spring的事务管理
- cookie记住密码