基于Alamofire的封装 - SwiftyNetwork

在使用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))
}

这里是对普通错误的一个接单回调。

总结

里面很多自定义的地方用的时候还是需要重新修改的,这个只是笔者在学习时写的一个二次封装,这里只是提供一个封装的想法供大家参考。笔者能力有限,大家有好的想法可以在评论区说出来。

你可能感兴趣的:(基于Alamofire的封装 - SwiftyNetwork)