问题
I have a bunch of view controllers (embedded navigation controller), and I need to make some async calls before I segue to the next screen. The problem is that I need to make this call at the time I click the button mapped to the segue, but since the async call hasn't returned yet, the segue is made and the next view controller is shown. How do people do this kind of thing to prevent view controller navigation happening before the async call is returned?
回答1:
TL;DR You can create an @IBAction for the UIButton and inside the function make the async call and launch the segue manually in the completionHandler using the dispatch_async(dispatch_get_main_queue()) {}.
To create your segue manually just Ctrl+Drag from the UIViewController to the next one like in the following picture:
And then you will see to choose the type of segue like in this picture:
After you choose the Show type you can see the segue in the hierarchy of view in your left choose it to set the identifier for the segue like in this picture:
You can handle your problem launching the segue manually with the function performSegueWithIdentifier, you can reference in the web to find a lot of tutorials about how to create a the segue manually using Interface Builder.
Once you segue has been created you can call it in anywhere you want, in your case as you will calling it inside a completionHandler of an async call you need to put in in the main thread using the dispatch_async(dispatch_get_main_queue()) {} function of Grand Central Dispatch.
Something like this code:
@IBAction func buttonTapped(sender: AnyObject) {
asyncFunction() {
dispatch_async(dispatch_get_main_queue()) {
self.performSegueWithIdentifier("someID", sender: sender)
}
}
}
Edit: Note that in Swift 3 the syntax has changed:
@IBAction func buttonTapped(_ sender: AnyObject) {
asyncFunction() {
DispatchQueue.main.async {
self.performSegueWithIdentifier("someID", sender: sender)
}
}
}
I hope this helps you.
回答2:
It sounds like you're looking for it to run synchronously; so if you're using GCD call dispatch_sync instead of dispatch_async when putting the heavy lifting on the background thread, and when you need the segue to happen put things back onto the main thread by calling dispatch_sync(dispatch_get_main_queue(), ^{ // handle error or segue }
来源:https://stackoverflow.com/questions/34954821/making-an-asynchronous-call-prior-to-a-segue-to-the-next-view-controller-swift