I would like to only execute a segue if I get a certain response from the server. In swift, how can I wait until I get a response to continue?
Bottom line, you don't "wait" for the response, but rather simply specify what you want to happen when the response comes in. For example, if you want to perform a segue when some network request is done, you should employ the completion handler pattern.
The issue here is that you're probably accustomed to just hooking your UI control to a segue in Interface Builder. In our case, we don't want to do that, but rather we want to perform the network request, and then have its completion handler invoke the segue programmatically. So, we have to create a segue that can be performed programmatically and then hook your button up to an @IBAction
that performs the network request and, if appropriate, performs the segue programmatically. But, note, there should be no segue hooked up to the button directly. We'll do that programmatically.
For example:
Define the segue to be between the two view controllers by control-dragging from the view controller icon in the bar above the first scene to the second scene:
Give that segue a storyboard identifier by selecting the segue and going to the "Attributes Inspector" tab:
Hook up the button (or whatever is going to trigger this segue) to an
@IBAction
.Write an
@IBAction
that performs network request and, upon completion, programmatically invokes that segue:@IBAction func didTapButton(_ sender: Any) { let request = URLRequest(...). // prepare request however your app requires let waitingView = showWaitingView() // present something so that the user knows some network request is in progress // perform network request let task = URLSession.shared.dataTask(with: request) { data, response, error in // regardless of how we exit this, now that request is done, let's // make sure to remove visual indication that network request was underway defer { DispatchQueue.main.async { waitingView.removeFromSuperview() } } // make sure there wasn't an error; you'll undoubtedly have additional // criteria to apply here, but this is a start guard let data = data, error == nil else { print(error ?? "Unknown error") return } // parse and process the response however is appropriate in your case, e.g., if JSON: // // guard let responseObject = try? JSONSerialization.jsonObject(with data) else { // // handle parsing error here // return // } // // // do whatever you want with the parsed JSON here // do something with response DispatchQueue.main.async { performSegue(withIdentifier: "SegueToSceneTwo", sender: self) } } task.resume() } /// Show some view so user knows network request is underway /// /// You can do whatever you want here, but I'll blur the view and add `UIActivityIndicatorView`. private func showWaitingView() -> UIView { let effectView = UIVisualEffectView(effect: UIBlurEffect(style: .Dark)) effectView.translatesAutoresizingMaskIntoConstraints = false view.addSubview(effectView) NSLayoutConstraint.activateConstraints([ effectView.leadingAnchor.constraintEqualToAnchor(view.leadingAnchor), effectView.trailingAnchor.constraintEqualToAnchor(view.trailingAnchor), effectView.topAnchor.constraintEqualToAnchor(view.topAnchor), effectView.bottomAnchor.constraintEqualToAnchor(view.bottomAnchor) ]) let spinner = UIActivityIndicatorView(activityIndicatorStyle: .WhiteLarge) effectView.addSubview(spinner) spinner.translatesAutoresizingMaskIntoConstraints = false NSLayoutConstraint.activateConstraints([ spinner.centerXAnchor.constraintEqualToAnchor(view.centerXAnchor), spinner.centerYAnchor.constraintEqualToAnchor(view.centerYAnchor) ]) spinner.startAnimating() return effectView }
来源:https://stackoverflow.com/questions/38617839/in-swift-how-can-i-wait-until-a-server-response-is-received-before-i-proceed