内容简介:网络请求是 App 中最常用的更能之一,除了 Apple 提供的 URLSession 之外,还有对其进行封装,功能更加强的的 Alamofire等强大的工具,尽管这样,我们依然会在自己的 App 中封装一套网络请求工具,以达到做网络请求时,代码简洁高效.做网络请求的时候尽量的简单,只需要少量的代码即可处理返回的数据现在已经可以做网络请求了,比如:把百度首页数据请求下来
网络请求是 App 中最常用的更能之一,除了 Apple 提供的 URLSession 之外,还有对其进行封装,功能更加强的的 Alamofire等强大的工具,尽管这样,我们依然会在自己的 App 中封装一套网络请求工具,以达到做网络请求时,代码简洁高效.
封装目的:
做网络请求的时候尽量的简单,只需要少量的代码即可处理返回的数据
封装过程:
1.实现网络请求单例,提供可修改 baseURL和 get post 请求方法.
enum RequestMethod { case post case get } ///请求对象 struct Requset { init(method: RequestMethod = .post, baseURL: String = "", path: String, parameters: [String : Any]?){ self.method = method self.baseURL = baseURL self.path = path self.parameters = parameters ?? [:] } var method: RequestMethod var baseURL: String var path: String var parameters: [String: Any] } ///网络工具 class NetworkManager { static let shared = NetworkManager("") init(_ baseURL: String = "") { self.baseUrl = baseURL } var baseUrl = "" func post(path: String,params: [String: Any]?,result: @escaping ((Result<Data,Error>)->())){ let request = Requset(baseURL:baseUrl, path: path, parameters: params) let target = Target(request: request) self.request(target: target, result: result) } func get(path: String,params: [String: Any]?,result: @escaping ((Result<Data,Error>)->())){ let request = Requset(baseURL:baseUrl, path: path, parameters: params) let target = Target(request: request) self.request(target: target, result: result) } private func request(target: Target,result: @escaping ((Result<Data,Error>)->())) { MoyaProvider<Target>().request(target) { (res) in switch res { case .success(let a): result(.success(a.data)) case .failure: result(.failure(res.error!)) } } } } 复制代码
现在已经可以做网络请求了,比如:把百度首页数据请求下来
NetworkManager("https://www.baidu.com").get(path: "", params: nil) { (res) in let data = try! res.get() print(String(data: data, encoding: .utf8)) } 复制代码
Optional("\r\n\r\n\r\n\r\n <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">\r\n <meta http-equiv="content-type" content="text/html;charset=utf-8">\r\n <meta content="always" name="referrer">\r\n <script src=" ss1.bdstatic.com/5eN1bjq8AAU… ">\r\n
2. 二次封装
仅仅这样封装很明显不能够达到精简的目的,这样其实和直接使用 Alamofire 没啥区别.
一般后台返回的数据都有固定的格式,比如:
{ "msg": "请求成功", "code": 1001, "data": {...} } 或者: { "msg": "请求成功", "code": 1001, "data": [...] } 复制代码
将其转换成对应的模型:
public struct DataResponse<T> { public init (){} public var code: Int = -1 public var msg: String = "" public var data: T? } public struct ListResponse<T> { public init (){} public var code: Int = -1 public var msg: String = "" public var data: [T] = [] } 复制代码
我们实现一个 Protocol 继承自 HandyJSON (HandyJSON本身也是协议),然后是我们的 Response 遵守这个协议.
public protocol RequestProtocol: HandyJSON { static func request(api: API, params: [String: Any]?, result: ((ResponseResult<Self>)->())?) } public extension RequestProtocol where Self: HandyJSON { static func request(api: API, params: [String: Any]?, result: ((ResponseResult<Self>)->())?) { let completionHandle: ((Result<Data,Error>)->()) = { res in switch res { case .success(let data): let jsonStr = String(data: data, encoding: .utf8) #if DEBUG print("url: \(api.path)") print("response:") print(jsonStr ?? "") #endif ///不是 json 数据,抛出 json 解析失败错误 guard let jsonObj = self.self.deserialize(from: jsonStr) else { result?(.failure(.deserializeFailed)) return } result?(.success(jsonObj)) case .failure(_): ///处理错误 抛出去 result?(.failure(.requestFailed)) } } if api.method == .post { NetworkManager.shared.post(path: api.path, params: params, result: completionHandle) }else{ NetworkManager.shared.get(path: api.path, params: params, result: completionHandle) } } } 复制代码
然后久可以如下优雅的做请求:
NetworkManager.shared.baseUrl = "https://api.douban.com" BookResponse.request(api: .getBookDetail, params: nil) { (res) in guard res.isSuccess else { return } print(res.value?.toJSON()) } 复制代码
{"msg":"invalid_apikey","code":104,"request":"POST /v2/book/1220562"}
API 是这么样的结构体
public struct API { var path: String var method: RequestMethod init(path: String, method: RequestMethod = .post) { self.path = path self.method = method } } ///可以通过这种方式 减少硬编码可能会带来的错误 extension API { static let getBookDetail = API(path: "/v2/book/1220562") } 复制代码
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- 通过可视化体验人工智能神经网络工具——TensorFlow PlayGround来认识神经网络
- 网络抓包调试代理工具大全、开发环境切换工具大全
- 网络工程师都知道的几款网络排障工具
- 2019 网络爬虫和相关工具
- Linux网络流量分析工具实现
- elecV2P:一款不止于 MITM 的网络工具
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。