等待asynchronous函数调用完成

我知道这个问题之前已经被问过,但所有的解决scheme都不适合我。

我有一个函数发送参数到一个API,并返回数据作为列表,我有一个UITableView设置使用该列表,但它运行之前列表分配给一个variables。

码:

var functionResult = [String]() override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view. //gradesscrollView.contentSize.height = 3000 fetchItems{ (str) in var returnedItems = [String]() let result = self.convertoArray(itemstoPass: str!) for i in result{ functionResult.append(i) } } self.tableofItems.delegate = self self.tableofItems.dataSource = self //Data source is set up to use functionResult, however functionResult is empty before fetchItem runs. } 

如果不立即投票表决,我将不胜感激,这是我所尝试过的。

  1. 派遣小组
  2. 信号量计时
  3. 运行variables
  4. 包括self.tableofItems.delegate = self& self.tableofItems.dataSource = self在fetchItems{ (str) in部分。

编辑:获取项目已请求,

 func fetchItems(completionHandler: @escaping (String?) -> ()) -> () { let headers = [ "Content-Type": "application/x-www-form-urlencoded" ] //Switch to keychain let username = UserDefaults.standard.object(forKey: "username") as! String? let password = UserDefaults.standard.object(forKey: "password") as! String? let usernametoSend = username! let passwordtoSend = password! print(usernametoSend) print(passwordtoSend) let parameters: Parameters = [ "username": usernametoSend, "password": passwordtoSend ] Alamofire.request("https://www.mywebsite.com/API/getItems", method: .post, parameters: parameters, headers: headers) .responseString { response in completionHandler(String(response.result.value!)) 

您不能 – 也不应该 – 等到asynchronous调用完成。 你需要学习asynchronous编程,直到你理解它。

asynchronous函数接受要做的工作,并在作业完成之前立即返回。

在Swift中,你通常编写一个asynchronous函数来完成一个完成处理程序,这是一个你想运行一个asynchronous任务完成的代码块。

我有一个名为Async_demo (链接)在Github上的项目,说明了这一点。 它实现了一个处理asynchronous下载的DownloadManager类。

关键部分是函数downloadFileAtURL() ,它应该更正确地命名为downloadDataAtURL,因为它返回的是内存数据而不是文件。

我创build了这个函数来完成处理程序作为参数:

 /** 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! } } 

它使用NSURLSession从指定的URL下载数据块。 我使用的数据请求调用需要在后台线程上执行的完成处理程序。 在我传递给数据任务的完成处理程序中,我调用传递给downloadFileAtURL()函数的完成处理程序,但在主线程上。

你发布的代码有点令人困惑。 目前还不清楚哪个部分是asynchronousfunction,stream程是什么,或者需要哪些数据来显示你的表格视图。

如果你重写asynchronous的函数来完成一个完成块,那么你可以在完成块中调用tableView.reloadData() 。 (确保在主线程上执行调用。)

编辑:

正如其他人所说,你需要编辑你的问题,以显示你的fetchItems()函数的代码。

我猜这个函数是Async的工作,并且它之后的块是一个asynchronous执行的完成处理程序。 如果是这样,你可能应该像这样重构你的代码:

 var functionResult = [String]() override func viewDidLoad() { super.viewDidLoad() //I moved these lines above the call to fetchItems to make it clear //that they run before fetchItems' completion closure is executed self.tableofItems.delegate = self self.tableofItems.dataSource = self //Data source is set up to use functionResult, however functionResult is empty before fetchItem runs. print("Step 1") fetchItems{ (str) in var returnedItems = [String]() let result = self.convertoArray(itemstoPass: str!) for i in result{ functionResult.append(i) } print("Step 3") DispatchQueue.main.async() { tableview.reloadData() //Do this from the main thread, inside the closure of `fetchItems()` } } print("Step 2") } 

您应该在loadView的方法中加载列表的数据,以便在UITableView读取之前加载它。

有时候, viewDidLoad会慢一点。 一般来说,人们会在loadView的方法中初始化list或sth的数据,以确保在创buildview之前数据已经完成。