在使用Alamofire这个第三方网络请求框架时,为了方便使用,对此进行了二次封装。尝试用自己的想法尽量向Swifty靠拢~
Demo地址
基本需求
- 使用枚举进行接口管理
- 使用枚举进行Error类型管理
- 使用枚举进行状态码管理
- 支持请求头带token
- 自定义响应体的结构
- 使用泛型直接返回模型实例
文件结构
|____Network-ResponseBody.swift
|____Network-Error.swift
|____Network-external.swift
|____Network-StatusCode.swift
|____Network-internal.swift
|____Network-Port.swift
示例
Network.default.testGet { (result) in
switch result {
case .success(let m):
print(m)
case .failure(let err):
print(err)
}
}
详细方法
端口
extension Network {
enum Port: String {
static let baseUrl = "http://www.mocky.io"
case testGet = "/v2/5bd6ab833500004900fd7c63"
}
}
extension Network.Port {
func string() -> String {
return Network.Port.baseUrl + rawValue
}
}
需要根据后台给的接口来修改这里
状态码
extension Network {
enum Statuscode: Int, Decodable {
case success = 200
case frequently = 400
case authenticationError = 401
case failed = 500
init(rawValue: Int) {
switch rawValue {
case 200...299:
self = .success
case 400:
self = .frequently
case 401...499:
self = .authenticationError
default:
self = .failed
}
}
}
}
通过Swift枚举给状态码赋予具体含义
错误
enum NetworkError: Error {
case `default`
case jsonDeserialization
case frequentlyError
case authorizationError
}
这里根据需要可以根据需要添加错误,方便辨别和处理,但需要和状态码一起使用
响应体
extension Network {
struct ResponseBody: Decodable {
let code: Statuscode
let data: T
let info: String
}
}
根据和后台协商,最后定下来的一个信息格式,需要注意的是data
必须是遵守Decodable
的
通用请求头设置
/// 通用请求头
private func commonHeaders(headers: HTTPHeaders?) -> HTTPHeaders {
var newHeaders: HTTPHeaders = [:]
if headers != nil {
newHeaders = headers!
}
if let tk = token {
newHeaders["Authorization"] = tk
}
return newHeaders
}
这里放置通用的请求头信息,这里默认添加token
主要方法
/// Data有返回数据的API请求入口
func request(
url: Port,
method: HTTPMethod,
parameters: Parameters? = nil,
encoding: ParameterEncoding = URLEncoding.default,
headers: HTTPHeaders? = nil,
completion: @escaping requestCompletion) {
UIApplication.shared.isNetworkActivityIndicatorVisible = true
let urlStr = url.string()
Alamofire.request(
urlStr,
method: method,
parameters: parameters,
encoding: encoding,
headers: commonHeaders(headers: headers)).responseData { (response) in
UIApplication.shared.isNetworkActivityIndicatorVisible = false
switch response.result {
case .success(let data):
self.successHandle(data: data, completion: completion)
case .failure(_):
self.failureHandle(completion: completion)
}
}
}
自己写的所有网络请求方法都应该汇入到这里,然后这里调用Alamofire
的网络请求方法进行操作。
成功处理
private func successHandle(data: Data, completion: requestCompletion) {
do {
guard let body = try? JSONDecoder().decode(ResponseBody.self, from: data) else {
throw NetworkError.jsonDeserialization
}
switch body.code {
case .success:
completion(Result.success(body.data))
case .frequently:
throw NetworkError.frequentlyError
default:
throw NetworkError.default
}
} catch(let error) {
if let err = error as? NetworkError {
completion(Result.failure(err))
}
}
}
这里是网络请求成功后调用的方法,先判断后台返回格式是否正确,再进行状态码的处理。这里最重要的是利用Swift
的泛型编程,对Decodable
进行反序列化,进行回调的时候可以直接将对象实例返回,无需再进行反序列化操作。
错误处理
private func failureHandle(completion: requestCompletion) {
completion(Result.failure(NetworkError.default))
}
这里是对普通错误的一个接单回调。
总结
里面很多自定义的地方用的时候还是需要重新修改的,这个只是笔者在学习时写的一个二次封装,这里只是提供一个封装的想法供大家参考。笔者能力有限,大家有好的想法可以在评论区说出来。