我知道这个问题以前曾被问过,但是所有解决方案都不适合我。
我有一个将参数发送到API的函数,并以列表的形式返回数据。我有一个UITableView设置为使用该列表,但是它在列表分配给变量之前运行。
码:
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. }
如果不立即将其作为重复投票,我将不胜感激,这是我尝试的方法。
self.tableofItems.delegate
self.tableofItems.dataSource
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!))
您不能-也不应该-等到异步调用完成。您需要学习异步编程,直到您了解它为止。
异步函数接受要执行的作业,并在作业完成之前立即返回。
在Swift中,您通常会编写一个异步函数来获取完成处理程序,这是您要在异步任务完成后运行的代码块。
我在Github上有一个名为 Async_demo (链接)的项目来说明这一点。它实现了处理异步下载的DownloadManager类。
关键部分是函数downloadFileAtURL(),应将其更恰当地命名为downloadDataAtURL,因为它返回内存中的数据而不是文件。
downloadFileAtURL()
我创建了该函数以将完成处理程序作为参数:
/** 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()函数但在主线程上的完成处理程序。
您发布的代码有点令人困惑。目前尚不清楚哪个部分是异步功能,流程是什么或显示表视图需要什么数据。
如果您重写执行异步工作的函数以获取完成块,则可以调用tableView.reloadData()完成块。(确保在主线程上执行调用。)
tableView.reloadData()
正如其他人所说,您需要编辑问题以显示fetchItems()功能代码。
fetchItems()
我猜想那个函数是做异步工作的那个函数,而它后面的那个块是一个异步执行的完成处理程序。如果是这样,您可能应该这样重构代码:
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") }