![](/img/trans.png)
[英]Swift wait for existing async operation to finish before starting a new one
[英]How to wait for a function to end on iOS/Swift, before starting the second one
我基本上必须使用在我的 viewDidLoad 中调用的方法。 第一个获取用户的搜索偏好并将偏好保存到顶部的变量。 之后我想在第二个 function 中访问和使用这些变量。但是现在当我想在第二个 function 中访问它们时,变量总是 nil。
怎么调整我的viewDidLoad,让第二个function只执行一次,我的数据请求就执行成功了?
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 或完成处理程序的内容。 也许有人可以发布一些我可以在我的 viewDidLoad 中使用并使其工作的代码?
你可以使用Swift闭包! 它们是为此而制造的。
请参阅Apple指南: 闭包
这是您在特定情况下需要的代码。
FinishedDownload是关闭。 当getTheSearchLocationAndRange()
,执行其代码直到completed()
行等待函数的所有进程完成。 一旦进程完成(例如下载), completed()
将调用闭包,该闭包激活getTheSearchLocationAndRange { () -> () in
定义的代码。 因此,只有在getTheSearchLocationAndRange()
完全执行并且数据存在(不是nil)时才调用loadDataFromDatabase()
)。
var searchLocation = String()
var searchLocationCoordinates = [String:Double]()
var searchRange = Int()
typealias FinishedDownload = () -> ()
override func viewDidLoad() {
super.viewDidLoad()
getTheSearchLocationAndRange()
}
func getTheSearchLocationAndRange(completed: FinishedDownload) {
// Code for searching Location Range HERE
completed()
}
getTheSearchLocationAndRange { () -> () in
loadDataFromDatabase()
}
我希望这解决了你的问题并回答了你的问题:)
顺便说一句,关于“离开你的GUI挂”部分,Alamofire会自动为您解决这个问题。 如果您不使用Alamofire,则必须手动将异步请求分配给后台线程,以便您的GUI不会无响应。
我写了一个演示项目并将其发布在GitHub上,模拟处理异步网络下载。 看看DuncanMC / SwiftCompletionHandlers 。
具体看一下方法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()
}
尝试这个
typealias FinishedMethod = ()
override func viewDidLoad() {
super.viewDidLoad()
SecondMethod(completed: FirstMethod())
}
func FirstMethod() {
// FirstMethod Code HERE
}
func SecondMethod(completed: FinishedMethod ) {
// SecondMethod Code HERE
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.