美文网首页
基于Alamofire的封装 - SwiftyNetwork

基于Alamofire的封装 - SwiftyNetwork

作者: Seacen_Liu | 来源:发表于2018-10-29 19:12 被阅读0次

    在使用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<T: Decodable>: 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<T: Decodable>(
        url: Port,
        method: HTTPMethod,
        parameters: Parameters? = nil,
        encoding: ParameterEncoding = URLEncoding.default,
        headers: HTTPHeaders? = nil,
        completion: @escaping requestCompletion<T>) {
        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<T: Decodable>(data: Data, completion: requestCompletion<T>) {
        do {
            guard let body = try? JSONDecoder().decode(ResponseBody<T>.self, from: data) else {
                throw NetworkError.jsonDeserialization
            }
            switch body.code {
            case .success:
                completion(Result<T>.success(body.data))
            case .frequently:
                throw NetworkError.frequentlyError
            default:
                throw NetworkError.default
            }
        } catch(let error) {
            if let err = error as? NetworkError {
                completion(Result<T>.failure(err))
            }
        }
    }
    

    这里是网络请求成功后调用的方法,先判断后台返回格式是否正确,再进行状态码的处理。这里最重要的是利用Swift的泛型编程,对Decodable进行反序列化,进行回调的时候可以直接将对象实例返回,无需再进行反序列化操作。

    错误处理

    private func failureHandle<T>(completion: requestCompletion<T>) {
        completion(Result<T>.failure(NetworkError.default))
    }
    

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

    总结

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

    相关文章

      网友评论

          本文标题:基于Alamofire的封装 - SwiftyNetwork

          本文链接:https://www.haomeiwen.com/subject/bpritqtx.html