最重要的是,您不必“等待”响应,而只是指定响应进入时要发生的情况.例如,如果您想在完成某些网络请求后执行检测,则应使用完成处理程序模式.
这里的问题是,您可能已经习惯于将UI控件挂接到Interface Builder中的序列上.在我们的例子中,我们不想这样做,而是想要执行网络请求,然后让其完成处理程序以编程方式调用segue.因此,我们必须创建可以以编程方式执行的segue,然后将您的按钮挂接到@IBAction上,该@IBAction执行网络请求,并在适当的情况下以编程方式执行segue.但是请注意,不应将segue直接挂接到按钮上.我们将以编程方式进行.
例如:
>通过将控件从第一个场景上方的栏中的视图控制器图标拖动到两个场景控制器之间,将segue定义为两个视图控制器之间:
>通过选择segue并转到“ Attributes Inspector”选项卡,为该segue提供故事板标识符:
>将按钮(或任何触发此segue的按钮)连接到@IBAction.
>编写一个@IBAction来执行网络请求,并在完成后以编程方式调用该序列:
@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
}