Swift-Alamofire二次封装

作者: PerhapYs | 来源:发表于2022-01-28 15:44 被阅读0次

    注:二次封装不仅需要Alamofire库,还需要HandyJSON库

    pod 'Alamofire', '5.5.0'
    pod 'HandyJSON', '5.0.2'
    

    1.错误信息

    enum ResponseError  :   Int {
    
        case    unkown      =    0
        case    success     =   200
        case    failure     =   500
        case    expaired    =   401
        case    beOffLine   =   402
    }
    

    2.服务器返回的数据转化为model后,存放在此结构中的.

    struct ResponseModel<T:HandyJSON>{
    
        var errorCode       :   ResponseError = .unkown
        var errorMessage    :   String = "未知错误"
        var model           :   T?
        var models          :   [T?]?
        var resultData      :   Any?
    }
    

    3.请求头

    struct RequestHeaders : HandyJSON{
    
        var timestamp       :   String?
        var token           :   String?
        var sign            :   String?
    }
    

    4.不需要返回参数时使用的默认Model

    struct ResponseDefault : HandyJSON {}
    

    5.服务器返回的最外层数据

    struct ResponseData : HandyJSON{
    
        var code    :   Int?
        var msg     :   String?
        var data    :   Any?
    }
    

    6.调用的类

    class NetManager {
    
    /// 单例
    public class var defualt : NetManager{
        struct Static {
            static let instance :NetManager = NetManager()
        }
        return Static.instance
    }
    
    /// 请求头
    var YJBHeaders : HTTPHeaders{
        get{
            var headers = RequestHeaders()
            headers.sign = ""
            headers.token = ""
            headers.timestamp = ""
            guard let jsonHeader = headers.toJSON() ,let jsonHeader = jsonHeader as? [String:String] else {
                return []
                }
            return HTTPHeaders.init(jsonHeader)
            }
        }
        /// 接口地址
        let RequestUrlHost : String = "http://test.17jbshop.com/"
    
        /// 参数编码方式
        let YJBParameterEncoder : ParameterEncoder = URLEncodedFormParameterEncoder.default
    }
    

    7.网络请求调用方法

    typealias ResponseBlock<T:HandyJSON> = (_ responseModel:ResponseModel<T>) -> ()
    
    extension NetManager{
    ///可无参数,无模型数据返回
    class func request(url:String,
                       method:HTTPMethod = .post,
                       parametersDic:[String:String]? = [:],
                       resultBlock:ResponseBlock<ResponseDefault>?){
        self.request(url: url, method: method, parametersDic: parametersDic, modelType: ResponseDefault.self, resultBlock: resultBlock)
    }
    /// 可无参数
    class func request<T:HandyJSON>(url:String,
                       method:HTTPMethod = .post,
                       parametersDic:[String:String]? = [:],
                       modelType:T.Type,
                       resultBlock:ResponseBlock<T>?){
        self.request(url: url, method: method, parameters: parametersDic, modelType: modelType, resultBlock: resultBlock)
    }
    /// 无模型数据返回
    class func request<Parameters: Encodable>(url:String,
                                              method:HTTPMethod = .post,
                                              parameters:Parameters,
                                              resultBlock:ResponseBlock<ResponseDefault>?){
        self.request(url: url, method: method, parameters: parameters, modelType: ResponseDefault.self, resultBlock: resultBlock)
    }
    
    /// 数据模型返回
    class func request<T:HandyJSON,Parameters: Encodable>(url:String,
                                                          method:HTTPMethod = .post,
                                                          parameters:Parameters,
                                                          modelType:T.Type,
                                                          resultBlock:ResponseBlock<T>?)
    {
        NetManager.InitDataRequest(url: url, method: method, parameters: parameters)
            .responseString { string in
                
                if let error = string.error{
                    print(error.errorDescription as Any)
                    return
                }
                self.response(modelType, string.value,resultBlock)
            }
        }
    }
    

    提取的相同配置:

    extension NetManager{
    
        fileprivate class func InitDataRequest<Parameters: Encodable>(url:String,
                               method:HTTPMethod = .post,
                               parameters:Parameters? = nil
        ) -> DataRequest{
        
            let headers : HTTPHeaders = NetManager.defualt.YJBHeaders
            let encoder : ParameterEncoder = NetManager.defualt.YJBParameterEncoder
            let requestUrl = url
        
            let request : DataRequest = AF.request(requestUrl, method: method, parameters: parameters, encoder: encoder, headers: headers, interceptor: nil, requestModifier: nil)
            return request
        }
    }
    

    数据转模型方法:

    ///解析服务器返回的数据转化为model
    fileprivate class func response<T:HandyJSON>
    (
        _ modelType:T.Type,
        _ responseData:String?,
        _ resultBlock:ResponseBlock<T>?
    ){
        guard let resultBlock = resultBlock else {
            return
        }
        var responseModel = ResponseModel<T>()
        let baseModel = ResponseData.deserialize(from: responseData)
        
        guard let baseModel = baseModel else {
            return resultBlock(responseModel)
        }
        responseModel.errorCode = ResponseError(rawValue: baseModel.code ?? 0) ?? .unkown
        if let _ = baseModel.msg{
            responseModel.errorMessage = baseModel.msg!
        }
        responseModel.resultData = baseModel.data
        
        // 当被转模型数据不存在,停止转模型.
        guard let data = baseModel.data else {
            
            return resultBlock(responseModel)
        }
        if let dataArray = data as? [Any]{          // 解析数组
            
            responseModel.models = [T].deserialize(from: dataArray)
            return resultBlock(responseModel)
        }
        else if let data = data as? [String : Any]{     //解析字典
            
                responseModel.model = T.deserialize(from: data)
                return resultBlock(responseModel)
            }
        else{   //原样返回Data数据
            return resultBlock(responseModel)
        }
    }
    

    8.举个例子:

    服务器数据结构:

    {
        code = 200,
        msg = "成功"  
        data = [
            {
                name = "haha",
                age = 1
            },
            {
                name = "hehe",
                age = 2
            }
        ]
    }
    

    请求参数,参数结构需要遵循Encodebale协议或者本身就遵循协议的[Sting,String]之类:

    class TestParam : Encodable{
        
        var id  : Int?
    }
    

    response model结构需要遵循HandyJSON协议,并且是data的数据结构:

    class TestModel : HandyJSON{
        
        var name : String?
        var age : Int?
    }
    

    发出请求:

    let API = "userInfo"
    let param = TestParam()
    param.id = 1
    NetManager.request(url:API,method:.post, parameters: param,modelType: TestModel.self { responseModel in
        // responseModel为ResponseModel类
    }
    

    注:如果data中的数据为字典则model为responseModel.model中,如果data为数组,则model为responseModel.models中.

    9.不足之处

    由于需求的特别性,可能有共同的请求参数,尝试过使用继承来达到目的,但是最终无法获取到对应的参数。同理返回参数中有共同参数也无法实现。目前只使用协议来标记参数和返回参数。
    代码地址:https://gitee.com/perhapys/alamofireSimpleUse

    相关文章

      网友评论

        本文标题:Swift-Alamofire二次封装

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