从另一个线程刷新UITableViewController

时间:2016-12-16 23:10:45

标签: ios swift uitableview swift2

我有后端向我的应用发送通知消息以通知用户下载新数据集。当用户收到通知时,会在推送通知线程中创建警告框,并要求用户接受或拒绝数据集下载。如果用户接受下载,则会以异步方式下载数据。我想要做的是,我想在下载完成后刷新表格视图。但我在不同的主题上,我不知道如何从该主题更新Tableview。我该怎么做?

func downloadContent(key: String, pinOnCompletion: Bool) {

        let manager = AWSUserFileManager.defaultUserFileManager()
        let content = manager.contentWithKey(self.prefix + key)

        content.downloadWithDownloadType(
            .IfNewerExists,
            pinOnCompletion: pinOnCompletion,
            progressBlock: {[weak self](content: AWSContent?, progress: NSProgress?) -> Void in
                guard self != nil else { return }
                /* Show progress in UI. */
            },
            completionHandler: {[weak self](content: AWSContent?, data: NSData?, error: NSError?) -> Void in
                guard self != nil else { return }
                if let error = error {
                    print("Failed to download a content from a server. \(error)")
                    return
                }
                if let fileData = data {
                    // Saves Data to core data here
                    //  Update the tableViewController

                }
                print("Object download complete.")
            })
    }

更新-1 这不是重复的帖子。建议的重复帖子询问如何从Tableviewcontroller类中的异步任务更新Tableviewcontroller。我的问题是从另一个类的另一个线程更新Tableviewcontroller

更新-2 为了澄清,下载管理器类中的这个下载函数是从实现AmazonPushNotificationManager的类中调用的。收到推送通知时会调用它。因此,当我调用下载时,我不再在UI线程上了。我是推送通知线程。如果我通过完成处理程序,那将来自推送通知线程,而不是来自UI。我有两个观点(一个是Tableview,另一个是UIViewController)。收到推送通知时,用户可以在任何一个上。因此,如果用户在UIViewController上,我不应该重新加载表数据。我希望这听起来并不令人困惑。

2 个答案:

答案 0 :(得分:2)

您不会从后台线程更新UI,而是切换回主线程,如下所示:

Swift 2:

    dispatch_async(dispatch_get_main_queue()) {
    self.tableView.reloadData()
}

...或

Swift 3

DispatchQueue.main.async {
    self.tableView.reloadData()
}

答案 1 :(得分:2)

正如其他人所说,你从后台线程更新表视图控制器等UI对象。这是明确禁止的。

你想要做的是在你的下载管理器类中编写一个函数(如果这是类是什么),它需要一个完成处理程序。编写downloadContent函数,以便在下载完成后调用完成处理程序。我在Github上有一个名为Async_demo(链接)的示例项目,它正好演示了这种技术。 (这个项目是用Swift 3编写的。此时你应该在Swift 3中进行新的开发。为什么你现在已经发布了Swift 3的Swift 2?)

关键功能是:

  /**
   This function demonstrates handling an async task.
   - Parameter url The url to download
   - Parameter completion: A completion handler to execute once the download is finished
   */


func downloadFileAtURL(_ url: URL, completion: @escaping DataClosure) {

  //We create a URLRequest that does not allow caching so you can see the download take place
  let request = URLRequest(url: url,
                           cachePolicy: .reloadIgnoringLocalAndRemoteCacheData,
                           timeoutInterval: 30.0)
  let dataTask = URLSession.shared.dataTask(with: request) {
    //------------------------------------------
    //This is the completion handler, which runs LATER,
    //after downloadFileAtURL has returned.
    data, response, error in

    //Perform the completion handler on the main thread
    DispatchQueue.main.async() {
      //Call the copmletion handler that was passed to us
      completion(data, error)
    }
    //------------------------------------------
  }
  dataTask.resume()

  //When we get here the data task will NOT have completed yet!
}

}