如何等待函数在iOS/Swift上结束,然后再启动第二个函数
我基本上必须创建方法,这些方法在我的viewDidLoad中被调用。第一个获取用户的搜索首选项,并将首选项保存到顶部的变量中。之后,我想在第二个函数中访问并使用这些变量。但是现在当我想在第二个函数中访问变量时,变量总是为零 我需要如何调整viewDidLoad,以便第二个函数只执行一次,并且我的数据请求已成功执行如何等待函数在iOS/Swift上结束,然后再启动第二个函数,ios,swift,Ios,Swift,我基本上必须创建方法,这些方法在我的viewDidLoad中被调用。第一个获取用户的搜索首选项,并将首选项保存到顶部的变量中。之后,我想在第二个函数中访问并使用这些变量。但是现在当我想在第二个函数中访问变量时,变量总是为零 我需要如何调整viewDidLoad,以便第二个函数只执行一次,并且我的数据请求已成功执行 var searchLocation = String() var searchLocationCoordinates = [String:Double]() var searchRa
var searchLocation = String()
var searchLocationCoordinates = [String:Double]()
var searchRange = Int()
override func viewDidLoad() {
super.viewDidLoad()
// Gets the user's search preference
getTheSearchLocationAndRange()
// Loads the data from the database
loadDataFromDatabase()
}
到目前为止,我已经阅读了dispatch_asynch或completion handler的内容。也许有人可以发布一些代码,我可以在我的viewDidLoad中使用这些代码并使其工作?您可以使用Swift闭包!他们就是为这个而生的 请参阅苹果指南: 这是您在特定情况下需要的代码 最终卸载是关闭。调用
getTheSearchLocationAndRange()
时,其代码将一直执行到completed()
行,该行等待函数的所有进程完成。一旦进程完成(例如下载),completed()
调用闭包,该闭包激活getTheSearchLocationAndRange{()->()中定义的代码。因此,loadDataFromDatabase()
只调用一次getTheSearchLocationAndRange()
已完全执行完毕,数据已存在(不是零)
我希望这解决了您的问题并回答了您的问题:)
顺便说一句,关于“让你的GUI挂起来”Alamofire会自动为您解决这一问题。如果您不使用Alamofire,那么您必须手动将异步请求分配给后台线程,这样您的GUI就不会没有响应。我编写了一个演示项目,并将其发布在GitHub上,模拟处理异步网络下载。请看
具体看一看asyncFetchImage()方法,它几乎和这个线程所说的完全一样:在内部使用一个异步方法,并在异步加载完成后调用一个完成块
这是您应该使用的一般模式。编写一个接受完成块/闭包的方法。在内部,让该方法调用它需要的任何异步函数,然后从异步方法调用的完成闭包内部调用完成闭包
函数asyncFetchImage
如下所示:
func asyncFetchImage(imageName imageName: String,
completion: (
image: UIImage?,
status: String) -> ())
{
print("Entering \(#function)")
//Simulate a network operation by waiting a few seconds before loading an image
let nSecDispatchTime = dispatch_time(DISPATCH_TIME_NOW, Int64(3.0 * Double(NSEC_PER_SEC)))
let queue = dispatch_get_main_queue()
dispatch_after(nSecDispatchTime, queue)
{
() -> Void in
let result = UIImage(named: imageName)
print("Loading image in background")
let status = result != nil ? "image loaded" : "Error loading image"
print("About to call completion handler")
completion(image: result, status: status)
}
print("Leaving \(#function)")
}
好的,我找到了一个解决方案。我基本上在第一个函数的末尾调用了这个函数
所以基本上:
var searchLocation = String()
var searchLocationCoordinates = [String:Double]()
var searchRange = Int()
override func viewDidLoad() {
super.viewDidLoad()
// Gets the user's search preference
getTheSearchLocationAndRange()
}
func getTheSearchLocationAndRange() {
// Code for getTheSearchLocationAndRange()
loadDataFromDatabase()
}
func loadDataFromDatabase(){
// Code for loadDataFromDatabase()
}
你没有这么说,但是getThSearchLocationAndRange必须是异步的?在这种情况下,你不应该等待,这会使你的GUI挂起。相反,你可以让第一个函数以完成块作为参数,然后把第二个函数作为块体,因为块体是实现它的一种方法,还有其他方法。好的,知道了!你有一些示例代码吗这让我明白了吗?但这也是我在其他帖子中看到的一个关于完成处理程序的想法!getTheSearchLocationAndRange中有调度函数吗?嗨,FredericP,还没有。@Mattk90你试过我在回答中发布的代码吗?问题是它使getTheSearchLocationAndRange()成为
函数不太有用,除非它总是调用loadDataFromDatabase
。如果你想让这个方法更灵活,就使用补全块方法。好的,我同意这一点。在我的情况下,我永远不需要两个函数都独立使用。因此我想我可以这样解决它。但我相信你,你解决了这个问题n可能是编程上更好的一个!如果其中一个进程在获取searchLocationAndRange()时花费更长的时间,则此进程可能会失败这根本不是一个解决方案。除了您的特定情况之外,这不是一个解决方案。它可能对您有效,但出于错误的原因。如果您在父函数中具有异步功能,则子函数仍将在不等待其他代码完成的情况下被排队调用。如果我在父函数中有参数呢我需要的GetTheSearchLocation和Range已返回
var searchLocation = String()
var searchLocationCoordinates = [String:Double]()
var searchRange = Int()
override func viewDidLoad() {
super.viewDidLoad()
// Gets the user's search preference
getTheSearchLocationAndRange()
}
func getTheSearchLocationAndRange() {
// Code for getTheSearchLocationAndRange()
loadDataFromDatabase()
}
func loadDataFromDatabase(){
// Code for loadDataFromDatabase()
}