美文网首页
iOS网络请求队列简单实现

iOS网络请求队列简单实现

作者: ray_1942 | 来源:发表于2019-08-07 10:34 被阅读0次

    翻遍百度没事找到合适的参考文章,最终找到了这篇以图片加载讲解队列的文章https://juejin.im/post/5b6047dae51d4517580e1627

    问题:项目进入首页需要进行多个多次的网络请求,如果有一个请求失败或者网络问题仍然会请求其他接口。(非AFN,原生网络请求方式)
    思路:让网络请求以队列的方式进行,先进先出,一个失败取消剩余请求。
    实现:

    1、保存请求的类

    //请求状态枚举
    enum RequestState {
        case new,start,failed,success
    }
    
    //请求记录
    class LZUrlRecord {
        let name: String
        let url:String
        var state = RequestState.new
        var dicParamter:Dictionary<String,Any>?
        var strParamter:String?
        
        var completion:((RequestState,Dictionary<String,Any>)->())?
        
        init(name:String,url:String){
            self.name = name
            self.url = url
        }
    }
    

    2、队列,及队列中Operation实现

    //保存队列操作的单例
    let sharePendingOperations = PendingOperations()
    
    class PendingOperations{
        //请求队列
        lazy var requestQueue:OperationQueue = {
            var queue = OperationQueue()
            queue.name = "Request queue"
            queue.maxConcurrentOperationCount = 1
            return queue
        }()
        //队列挂起
        func suspendAllOperations()  {
            self.requestQueue.isSuspended = true
        }
        // 队列重启
        func resumeAllOperations() {
            self.requestQueue.isSuspended = false
        }
        // 重置队列
        func resetAllOperations() {
            self.requestQueue.cancelAllOperations()
            self.resumeAllOperations()
        }
        
    }
    //Operation是一个抽象类,专为子类化而设计。每个子类代表一个特定的任务,如前面的图所示。
    
    //自定义请求任务
    class LZRequestTask: Operation {
    
        let urlRecord:LZUrlRecord
        
        init(_ urlRecord:LZUrlRecord){
            self.urlRecord = urlRecord
        }
        
        override func main() {
            //每次启动一个operation时将整个队列挂起,暂停所有operations
            sharePendingOperations.suspendAllOperations()
            //发起网络请求
            RNetUtil.shareManager.requestTPOST(url: urlRecord.url, paramter: urlRecord.strParamter!) { (state, data) in
           //有回调将网络状态及请求结果返回
                if let handler = self.urlRecord.completion{
                    self.urlRecord.state = state
                    handler(state, data)
                }
            }
        }
    }
    
    

    3、网络请求

    //网络请求
     func requestPOSTWithQueue(url:String,
                                  paramter:String,
                                  completion:@escaping ((RequestState,Dictionary<String,Any>)->Void)) {
          //定义请求记录实例
            let urlRecord = LZUrlRecord.init(name: url, url: url)
            urlRecord.strParamter = paramter
          // 实现回调
            urlRecord.completion = {
                (state,data) in
                if state == .success{
                    // 成功时重新启动操作队列
                    sharePendingOperations.resumeAllOperations()
                }else{
                    //  失败时重置操作队列
                    sharePendingOperations.resetAllOperations()
                }
                 //将网络状态和返回值传回主线程刷新ui
                completion(state,data)
            }
            // 网络请求任务实例
            let requestTask = LZRequestTask.init(urlRecord)
            //将网络请求任务加入操作队列
             sharePendingOperations.requestQueue.addOperation(requestTask)
    
        }
    

    4、viewController里发起网络请求

    //同时发起多个网络请求
    func testRequestTasks() {
          RNetUtil.shareManager.requestPOSTWithQueue(url: url, paramter: "0") { (state, data) in
              print(state,data)
          }
          RNetUtil.shareManager.requestPOSTWithQueue(url: url, paramter: "0") { (state, data) in
              print(state,data)
          }
          RNetUtil.shareManager.requestPOSTWithQueue(url: url, paramter: "0") { (state, data) in
              print(state,data)
          }
      }
    

    5、请求结果
    失败时


    失败时.gif

    成功时


    成功时.gif

    基本解决了文章开头提出的问题。

    有什么改进意见或者好的想法,欢迎大家提出。

    相关文章

      网友评论

          本文标题:iOS网络请求队列简单实现

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