iOS网络请求队列简单实现

2019-08-07  本文已影响0人  ray_1942

翻遍百度没事找到合适的参考文章,最终找到了这篇以图片加载讲解队列的文章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

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

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

上一篇下一篇

猜你喜欢

热点阅读