Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios 在处理HTTP请求后重新加载UITableView_Ios_Swift_Uitableview - Fatal编程技术网

Ios 在处理HTTP请求后重新加载UITableView

Ios 在处理HTTP请求后重新加载UITableView,ios,swift,uitableview,Ios,Swift,Uitableview,假设我有两个类:一个类表示执行HTTPGET请求的数据库 func getObjects(completion: (([Object]) -> Void)?) { guard let url = // ... let session = URLSession(configuration: .default) let task = session.dataTask(with: url) { (data, response, error) in Dispatch

假设我有两个类:一个类表示执行HTTPGET请求的数据库

func getObjects(completion: (([Object]) -> Void)?) {

  guard let url = // ...

  let session = URLSession(configuration: .default)
    let task = session.dataTask(with: url) { (data, response, error) in
      DispatchQueue.main.async {
        if let error = error {
          fatalError("Dispatching main queue failed: \(error)")
        } else if let data = data {
          let decoder = JSONDecoder()

          do {
            let objects = try decoder.decode([Object].self, from: data)
            completion?(object)
          } // ...
    // ...
    }
  task.resume()
}  
相应的结果对象数组被传递给另一个类UIViewController。因为我基于不同的配置对象实例化了多个数据库,所以我希望在分区UITableView中显示排序的结果

func load(then: (([(DatabaseConfig?, [Object])]) -> Void)) {
  var allObjects: [(DatabaseConfig?, [Object])] = [(nil, [])]

  Storage.loadDatabaseConfigs(completion: { configs in
    self.configs = configs
  })

  for config in self.configs {
    var objectSection: (DatabaseConfig?, [Object]) = (nil, [])

    let database = Database.init(config: config)

    objectSection.0 = config
    database.getObjects(completion: { objects in
      objectSection.1.append(objects)
    })
    allObjects.append(allObjectsInSection)
  }

  then(allObjects)
}
加载和“格式化”工作正常

我在
viewwillispect()
中调用
load(then:)
函数,将结果传递给类数组,该数组保存TableView的所有最终条目。然后,我尝试重新加载数据

override func viewWillAppear(_ animated: Bool) {
  super.viewWillAppear(true)
    self.load(then: { objects in
      self.allObjects = objects
      self.tableView.reloadData()
    })
}

我知道GET请求需要时间,所以我的问题是:如何或在何处重新加载UITableView?我显然需要确保GET请求已成功执行,然后重新加载。我已经尝试为重新加载而调用
DispatchQueue.main.async
,但没有成功。

由于您发出了多个请求,因此在所有请求完成之前,您确实不想调用
然后
闭包。您可能需要使用
DispatchGroup
来实现此目的

func load(then: (([(DatabaseConfig?, [Object])]) -> Void)) {
    var allObjects: [(DatabaseConfig?, [Object])] = [(nil, [])]

    Storage.loadDatabaseConfigs(completion: { configs in
        self.configs = configs

        let dispatchGroup = DispatchGroup()
        for config in self.configs {
            dispatchGroup.enter()
            var objectSection: (DatabaseConfig?, [Object]) = (nil, [])

            let database = Database.init(config: config)

            objectSection.0 = config
            database.getObjects(completion: { objects in
                objectSection.1.append(objects)
                dispatchGroup.leave()
            })
            allObjects.append(allObjectsInSection)
        }
        dispatchGroup.notify(queue: .main) {
            then(allObjects)
        }
    })
}

编辑:正如@Macistador所指出的,loadDatabaseConfigs是异步的,因此数据库调用应该在该函数的
完成
回调中进行。

由于您发出了多个请求,在所有请求完成之前,您确实不想调用
然后
闭包。您可能需要使用
DispatchGroup
来实现此目的

func load(then: (([(DatabaseConfig?, [Object])]) -> Void)) {
    var allObjects: [(DatabaseConfig?, [Object])] = [(nil, [])]

    Storage.loadDatabaseConfigs(completion: { configs in
        self.configs = configs

        let dispatchGroup = DispatchGroup()
        for config in self.configs {
            dispatchGroup.enter()
            var objectSection: (DatabaseConfig?, [Object]) = (nil, [])

            let database = Database.init(config: config)

            objectSection.0 = config
            database.getObjects(completion: { objects in
                objectSection.1.append(objects)
                dispatchGroup.leave()
            })
            allObjects.append(allObjectsInSection)
        }
        dispatchGroup.notify(queue: .main) {
            then(allObjects)
        }
    })
}

编辑:正如@Macistador所指出的,loadDatabaseConfigs是异步的,因此数据库调用应该在该函数的
完成
回调中进行。

url请求是否有任何错误?因此,如果我理解正确,问题是您正在发出多个请求,并且希望在所有请求完成后重新加载表视图?url请求是否有任何错误?因此,如果我理解正确,问题是您正在发出多个请求,并且希望在所有请求完成后重新加载表视图?由于loadDatabaseConfigs似乎是异步的,因此最好将所有内容都移动到完成中closure@Macistador没错。我没注意到,谢谢你。我仍然不确定将
self.tableView.reloadData()放在哪里
。除此之外:您确定进入和离开调度组属于for循环而不是它的外部吗?您需要为每个getObjects调用匹配enter()和leave()调用,并且需要在每个配置的getObjects调用完成时执行leave()。如果在循环之外执行,则使用DispatchGroup没有任何意义,因为它将在同一runloop内进入和离开,导致立即执行其notify回调。您不需要将调用移动到self.tableView.reloadData()。保持原样。由于loadDatabaseConfigs似乎是异步的,所以最好将所有内容都移动到完成中closure@Macistador没错。我没注意到,谢谢你。我仍然不确定将
self.tableView.reloadData()放在哪里
。除此之外:您确定进入和离开调度组属于for循环而不是它的外部吗?您需要为每个getObjects调用匹配enter()和leave()调用,并且需要在每个配置的getObjects调用完成时执行leave()。如果在循环之外执行,则使用DispatchGroup没有任何意义,因为它将在同一runloop内进入和离开,导致立即执行其notify回调。您不需要将调用移动到self.tableView.reloadData()。放在原处。