在重新加载 table 视图之前完成了两个服务器请求

Two server requests completed before reloading the table view

我有这两个请求要在重新加载 table 视图之前完成(table 视图取决于它们)。

我试过下面的方法,但没有用。

请求 1 完成,然后 table 视图在请求 2 完成之前重新加载。

DispatchQueue.global(qos: DispatchQoS.QoSClass.default).async {
        //1. request 1:
        self.serverRequestAuth("/request1")
        //2. request 2:
        self.serverRequestAuth("/request2")
            DispatchQueue.main.async{
                //3. reload the table view
                self.tableView.reloadData()
            }
    }

我应该如何进行?

提到:serverRequestAuth包含服务器请求,json的解析,里面字典的解析

方法 serverRequestAuth:

func serverRequestAuth(_ requestName: String){
    let requestNameEscaped = requestName.addingPercentEncoding(withAllowedCharacters: CharacterSet.urlQueryAllowed)!


    var request = NSMutableURLRequest()
    request = NSMutableURLRequest(url: URL(string: "\(self.view.getServerPath())\(requestNameEscaped)")!, cachePolicy: NSURLRequest.CachePolicy.reloadIgnoringLocalCacheData, timeoutInterval: 5)

    request.httpMethod = "GET"
    request.setValue(self.view.getAuth(), forHTTPHeaderField: "Authorization")
    request.setValue("application/json", forHTTPHeaderField: "Content-Type")

    let task = URLSession.shared.dataTask(with: request as URLRequest) {data, response, err in
        if data != nil {
            if let dictionary = self.parseJSONData(data!) {
                self.parseDictionary(dictionary, typeOfRequest: requestName)
            }
        }
    }
    task.resume()
}

尝试使用DispatchSemaphore

func serverRequestAuth(_ requestName: String){
    let requestNameEscaped = requestName.addingPercentEncoding(withAllowedCharacters: CharacterSet.urlQueryAllowed)!

    let semaphore = DispatchSemaphore(value: 0);
    var request = NSMutableURLRequest()
    request = NSMutableURLRequest(url: URL(string: "\(self.view.getServerPath())\(requestNameEscaped)")!, cachePolicy: NSURLRequest.CachePolicy.reloadIgnoringLocalCacheData, timeoutInterval: 5)

    request.httpMethod = "GET"
    request.setValue(self.view.getAuth(), forHTTPHeaderField: "Authorization")
    request.setValue("application/json", forHTTPHeaderField: "Content-Type")

    let task = URLSession.shared.dataTask(with: request as URLRequest) {data, response, err in
        if data != nil {
            if let dictionary = self.parseJSONData(data!) {
                self.parseDictionary(dictionary, typeOfRequest: requestName)
                semaphore.signal();
            }
        }
    }
    task.resume()
    semaphore.wait(timeout: .distantFuture)
}

试试这个:

func serverRequestAuth(_ requestName: String, control:@escaping (_ check : Bool)-> Void){
    let requestNameEscaped = requestName.addingPercentEncoding(withAllowedCharacters: CharacterSet.urlQueryAllowed)!


    var request = NSMutableURLRequest()
    request = NSMutableURLRequest(url: URL(string: "\(self.view.getServerPath())\(requestNameEscaped)")!, cachePolicy: NSURLRequest.CachePolicy.reloadIgnoringLocalCacheData, timeoutInterval: 5)

    request.httpMethod = "GET"
    request.setValue(self.view.getAuth(), forHTTPHeaderField: "Authorization")
    request.setValue("application/json", forHTTPHeaderField: "Content-Type")

    let task = URLSession.shared.dataTask(with: request as URLRequest) {data, response, err in
        if data != nil {
            if let dictionary = self.parseJSONData(data!) {
                self.parseDictionary(dictionary, typeOfRequest: requestName)
                control(true)
            }else{

                control(false)
            }
        }
    }
    task.resume()
}

你可以这样调用它:

serverRequestAuth("myStringRequest1", control: {(check)in

        if check  {
            self.serverRequestAuth("myStringRequest2", control: {(check) in

                if check {

                    self.tableView.reloadData()

                }else{

                    print("error Request 2")
                }
            })


        }else {

            print("error request 1")

        }
    })

我曾经遇到过类似的问题。为了提供一个简单的解决方案,我编写了这个小型库:

https://github.com/prine/ROConcurrency

您可以将请求分组到任务中,等待所有请求完成,然后重新加载 table。

var taskRequest1 = TaskComplex { (finished) -> () in
    self.serverRequestAuth("/request1", finished)
}

var taskRequest2 = TaskComplex { (finished) -> () in
    self.serverRequestAuth("/request2", finished)
}

var reloadTable = TaskComplex { (finished) -> () in
    DispatchQueue.main.async{
         // 3. reload the table view
         self.tableView.reloadData()
         finished()
    }
}

var barrierComplex = BarrierComplex(tasks: [taskRequest1, taskRequest2], afterTask: reloadTable)
barrierComplex.startTasks()

您的 serverRequestAuth 方法需要告知其异步完成的时间,因此您需要添加完成的回调:

func serverRequestAuth(_ requestName: String, _ finished:(Bool) -> ()) {
    let requestNameEscaped = requestName.addingPercentEncoding(withAllowedCharacters: CharacterSet.urlQueryAllowed)!


    var request = NSMutableURLRequest()
    request = NSMutableURLRequest(url: URL(string: "\(self.view.getServerPath())\(requestNameEscaped)")!, cachePolicy: NSURLRequest.CachePolicy.reloadIgnoringLocalCacheData, timeoutInterval: 5)

    request.httpMethod = "GET"
    request.setValue(self.view.getAuth(), forHTTPHeaderField: "Authorization")
    request.setValue("application/json", forHTTPHeaderField: "Content-Type")

    let task = URLSession.shared.dataTask(with: request as URLRequest) {data, response, err in
        if data != nil {
            if let dictionary = self.parseJSONData(data!) {
                self.parseDictionary(dictionary, typeOfRequest: requestName)

                // Here you call finished to tell the Barrier that its finished
                finished()
            }
        }
    }
    task.resume()
}