代码之家  ›  专栏  ›  技术社区  ›  JamMan9

为什么我的完成处理程序不处理我的URLSession?

  •  0
  • JamMan9  · 技术社区  · 6 年前

    我的应用程序遇到了一个小问题。在粘贴任何代码之前,让我提供一点上下文。我有一个带有动态单元格的表格视图。每个单元格包含一个按钮。当我按下单元格内的按钮时,会调用一个函数,它发出一个URLSession数据任务请求。我使用一个可解码的类来存储JSON结果,我所要做的就是打印结果数组的计数。我遇到的问题;打印在返回结果之前发生。

    为了解决这个问题,我尝试使用完成处理程序,并在DispatchGroup内运行urlsession,直到DispatchGroup结束后才打印。

    我希望有人能快速查看我的代码并指出我的错误。

    以下是我的函数,我在其中提出会话请求:

    func loadLocalPrice(selectedItemName: String, completion: @escaping (_ result: [PriceModel])-> Void) {
    
        var localPrice = [PriceModel]()
    
        let urlApi = "http://my.url.com/category/"+self.selectedCategory+"/"+selectedItemName
    
        guard let url = URL(string: urlApi) else {return completion(localPrice)}
    
        URLSession.shared.dataTask(with: url) { (data, response, error) in
            guard let data = data else {return}
            self.dispatchGroupLoadItems.enter()
            do {
                localPrice = try JSONDecoder().decode([PriceModel].self, from: data)
                print("The result inside the function is: \(localPrice.count)")
            } catch let JSONerror {
                print("error decoding JSON", JSONerror)
            }
            self.dispatchGroupLoadItems.leave()
    
            }.resume()
            return completion(localPrice)
    }
    

    下面是调用包含urlsession的上述函数的函数:

        func addToBasket(sender: UIButton, name: String?, category: String?) {
        var localPrice = [PriceModel]()
    
        DispatchQueue.main.async {
            self.loadLocalPrice(selectedItemName: name!) {
                (result: [PriceModel]) in
                print("got back inside the dispatchGroup: \(result.count)")
    
                localPrice = result
            }
    
    
            self.dispatchGroupLoadItems.notify(queue: .main) {
                print("Got back outside the dispatchGroup: \(localPrice.count)")
            }
        }
    }
    

    下面是我的控制台输出,因此您可以看到返回结果的顺序:

    got back inside the dispatchGroup: 0
    Got back outside the dispatchGroup: 0
    The result inside the function is: 1
    
    3 回复  |  直到 6 年前
        1
  •  1
  •   Kamran    6 年前

    你只是不需要 dispatchGroup 当您已经有一个完成处理程序时。您的问题可以通过使用 completion 以如下正确的方式处理,

    func loadLocalPrice(selectedItemName: String, completion: @escaping (_ result: [PriceModel])-> Void) {
    
        var localPrice = [PriceModel]()
    
        let urlApi = "http://my.url.com/category/"+self.selectedCategory+"/"+selectedItemName
    
        guard let url = URL(string: urlApi) else { 
                  completion(localPrice)
                  return 
                }
    
        URLSession.shared.dataTask(with: url) { (data, response, error) in
            guard let data = data else {
                   completion(localPrice)
                   return
                 }
            do {
                localPrice = try JSONDecoder().decode([PriceModel].self, from: data)
            } catch let JSONerror {
                print("error decoding JSON", JSONerror)
            }
            DispatchQueue.main.async {
              completion(localPrice)
            }
         }.resume() 
    }
    
    func addToBasket(sender: UIButton, name: String?, category: String?) {
        var localPrice = [PriceModel]()
    
        self.loadLocalPrice(selectedItemName: name!) {
            (result: [PriceModel]) in
            print("Count: \(result.count)")
            localPrice = result
        }
    }
    
        2
  •  1
  •   whoover    6 年前

    你不需要派遣组就可以返回这里。

     func loadLocalPrice(selectedItemName: String, completion: @escaping (_ result: [PriceModel])-> Void) {
    
          var localPrice = [PriceModel]()
    
          let urlApi = "http://my.url.com/category/"+self.selectedCategory+"/"+selectedItemName
    
          guard let url = URL(string: urlApi) else {
               completion(localPrice)
               return
          }
    
        URLSession.shared.dataTask(with: url) { (data, response, error) in
            guard let data = data else {
                completion(localPrice)
                return
            }
            do {
                localPrice = try JSONDecoder().decode([PriceModel].self, from: data)
                print("The result inside the function is: \(localPrice.count)"  
            } catch let JSONerror {
                print("error decoding JSON", JSONerror)
            }
            completion(localPrice)
        }.resume()
    }
    
        3
  •  1
  •   Ido    6 年前

    问题是你试图 return completion(localPrice) . 首先, URLSession.shared.dataTask(with: url) 正在后台运行,因此不需要使用 dispatchGroupLoadItems .

    你要做的就是给你打电话 completion block 在主线程上 urlsession.shared.datatask(带:url) 完井区块 就像这样:

    func loadLocalPrice(selectedItemName: String, completion: @escaping (_ result: [PriceModel])-> Void) {
        var localPrice = [PriceModel]()
        let urlApi = "http://my.url.com/category/"+self.selectedCategory+"/"+selectedItemName
        guard let url = URL(string: urlApi) else {
            completion(localPrice)
            return
        }
    
        URLSession.shared.dataTask(with: url) { (data, response, error) in
            guard let data = data else {return}
            do {
                localPrice = try JSONDecoder().decode([PriceModel].self, from: data)
                print("The result inside the function is: \(localPrice.count)")
            } catch let JSONerror {
                print("error decoding JSON", JSONerror)
            }
    
            DispatchQueue.main.async {
                completion(localPrice)
            }
        }.resume()
    }
    

    以及 addToBasket 功能变为:

    func addToBasket(sender: UIButton, name: String?, category: String?) {
        var localPrice = [PriceModel]()
    
        self.loadLocalPrice(selectedItemName: name!) {(result: [PriceModel]) in
            print("The result from completion block: \(result.count)")
    
            localPrice = result
        }
    }