swift中网络请求库的封装(Alamofire+HandyJSON)

swift中网络请求库的封装(Alamofire+HandyJSON)

我们用swift语言来写iOS的程序,会用Alamofire+HandyJSON来取代AFNetworking+MJExtension,怎么样封装成正确姿势来发起网络请求,我个人封装一个,有待优化的地方,还请指正,话不多说,我们上代码。

这里我们需要先拓展一下Alamofire中的DataRequest类

extension DataRequest {
  //处理接口中返回的data是对象的时候 data:{},这里在请求方法中利用了范型,HandyJSON框架可以将json转换为范型(model),keypath是我加一层获取到的路径,比如说你需要的东西在data里的层级比较深,你想直接取到你需要的东西。
    private static func handyModelResponseSerializer<T: HandyJSON>(keyPath: String? = nil,
    							options: JSONSerialization.ReadingOptions = .allowFragments)
        -> DataResponseSerializer<T>
    {
        return DataResponseSerializer { _, response, data, error in
            guard error == nil else { return .failure(error!) }
            guard let validData = data, validData.count > 0 else {
                    return .failure(AFError.responseSerializationFailed(reason: .inputDataNilOrZeroLength))
             }
//这里用到了 SwiftyJSON来将data转为json,当然你也可以自己用JSONSerialization去转
            let json = try? JSON(data: validData)
            var keyPathArr: [JSONSubscriptType] = []
            if let keyPath = keyPath , keyPath.isEmpty == false{
                keyPathArr = keyPath.components(separatedBy: ".").map{value -> JSONSubscriptType in
                    return Int(value) == nil ? value : Int(value)!
                }
            }
//重点在这里,HandyJSON将json转为了范型
            if let model = T.deserialize(from: JSON(validData)[keyPathArr].rawString(), designatedPath: nil){
                return .success(model)
            }else{
                return .failure(AFError.responseSerializationFailed(reason: .inputDataNilOrZeroLength))
            }
        }
    }

    func va_responseModel<T: HandyJSON>(keyPath: String? = nil, completionHandler: @escaping (DataResponse<T>) -> Void) -> Self {
        return response(
            queue: nil,
            responseSerializer: DataRequest.handyModelResponseSerializer(keyPath: keyPath, options: .allowFragments),
            completionHandler: completionHandler
        )
    }


    //这里是对data类型为数组的处理,data:[],同上,返回值是 [T]
    private static func handyModelArrayResponseSerializer<T: HandyJSON>(keyPath: String? = nil,
                                                          options: JSONSerialization.ReadingOptions = .allowFragments)
        -> DataResponseSerializer<[T]>
    {
        return DataResponseSerializer { _, response, data, error in
            guard error == nil else { return .failure(error!) }
            
            guard let validData = data, validData.count > 0 else {
                return .failure(AFError.responseSerializationFailed(reason: .inputDataNilOrZeroLength))
            }
            
            var keyPathArr: [JSONSubscriptType] = []
            if let keyPath = keyPath , keyPath.isEmpty == false{
                keyPathArr = keyPath.components(separatedBy: ".").map{value -> JSONSubscriptType in
                    return Int(value) == nil ? value : Int(value)!
                }
            }
            if let model = [T].deserialize(from: JSON(validData)[keyPathArr].rawString(), designatedPath: nil){
                return .success(model.flatMap{$0})
            }else{
                return .failure(AFError.responseSerializationFailed(reason: .inputDataNilOrZeroLength))
            }
        }
    }
    
    func va_responseModelArray<T: HandyJSON>(keyPath: String? = nil, completionHandler: @escaping (DataResponse<[T]>) -> Void) -> Self {
        return response(
            queue: nil,
            responseSerializer: DataRequest.handyModelArrayResponseSerializer(keyPath: keyPath, options: .allowFragments),
            completionHandler: completionHandler
        )
    }
}

模型的转化,我们已经写完了,下面我们来写网络请求类

class NetworkRequest :SessionManager{
    
    //单例配置
    static let shareInstance = NetworkRequest()
  
    fileprivate init() {
        let config = URLSessionConfiguration.default
        config.timeoutIntervalForRequest = 10 //请求超时的时长
        super.init(configuration: config)
    }
    
    fileprivate static var dataRequest :DataRequest?    //请求例集合
    
    //MARK:- ====================================== 请求处理 ==================================
    static func cancelLast(){
        dataRequest?.cancel()
    }
    
    
    static func request(method:HTTPMethod,urlString: String, params : [String : Any]?) -> DataRequest{
 	   //这里是请求头,根据你的需求来写
        var headers: [String: String] = [:]
        headers["Authorization"] = "Bearer " + AITAccount.token 
        
        let dataRequest = shareInstance.request(urlString, method: method, parameters: params, headers: headers)
        self.dataRequest = dataRequest
        return dataRequest
    }
    //baseModel,见下文的基础model类
    static func requestModel<T: HandyJSON, B: BaseModel<T>>(method: HTTPMethod,urlString: String, params: [String: Any]?,keyPath: String? = nil,handler: @escaping ((B?) -> Void)){
        
        _ = request(method: method, urlString: urlString, params: params).va_responseModel(keyPath: keyPath) { (response: DataResponse<B>) in
            AITHud.dismissLoading()
            if let val = response.value{
               
                    if val.status_code !=“成功的code”{
                        if let msg = val.message {
                            if msg.count > 0  {
                                //展示你的错误信息
                            }
                        }else{
                            // "请求失败"
                        }
                    }
                    if val.forbidden == "true" {
                        if let msg = val.message{
                            if msg.count > 0 {
                                //展示你的错误信息
                            }
                        }
                    }
                    handler(val)
            }else{
                //请求失败
                handler(nil)
            }
        }
    }
}

到这里,我们的请求已经完成了,接下来就是数据的处理,我们需要的模型是需要继承handyjson的,因为我们请求中的范型是指向handyjson类型的

//这里是你的错误定义
enum ResultCodeType :String{
    case IsNotlogin = "" //缺少token
    case NewToken = "" //新的token
    case InvalidToken = "" //token无效
    case SuccessResponse = ""    //正确响应
    case SubmitError = "" //表单提交验证信息错误
    case OtherError = "" //其他错误信息
}


class BaseModel<TT: HandyJSON>: HandyJSON{
    
    var status_code :String? //状态码
    var message :String? //信息
    var model: TT? //对象模型
    var modelArr: [TT]? //数组模型
    var data : Any?

    
    func mapping(mapper: HelpingMapper) {
        mapper <<<
            self.model <-- "data"
        mapper <<<
            self.modelArr <-- "data"
    }
    required init() {}
    
    required init?(coder aDecoder: NSCoder) {fatalError("init(coder:) has not been implemented")}
}

好了,我们的封装完成了,下面给大家介绍下简单的使用。

//在basemodel<写入你要返回的model,要继承handyjson>
NetworkRequest.requestModel(method: .get, urlString: KLiving, params: nil) { [weak self]  (res:BaseModel<TempModel>?) in
            //如果是对象,res?.model
            let model = res?.model
            //如果是数组,res?.modelArr
            let arr = res?.modelArr
 }
  • 12
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值