迅速,我如何才能等到收到服务器响应后再继续?
Posted
技术标签:
【中文标题】迅速,我如何才能等到收到服务器响应后再继续?【英文标题】:In swift, how can I wait until a server response is received before I proceed? 【发布时间】:2016-07-27 15:52:20 【问题描述】:如果我从服务器获得特定响应,我只想执行一个 segue。在swift中,我怎样才能等到收到回复才能继续?
【问题讨论】:
使用completionHandler: ***.com/questions/8427836/… 你几乎不想主动等待,因为这会阻塞你当前的线程。 【参考方案1】:最重要的是,您不会“等待”响应,而是简单地指定响应到来时您想要发生的事情。例如,如果您想在完成某些网络请求时执行 segue,您应该使用完成处理程序模式。
这里的问题是,您可能习惯于将 UI 控件与 Interface Builder 中的 segue 挂钩。在我们的例子中,我们不想这样做,而是想要执行网络请求,然后让它的完成处理程序以编程方式调用 segue。因此,我们必须创建一个可以以编程方式执行的 segue,然后将您的按钮连接到执行网络请求的@IBAction
,并在适当的情况下以编程方式执行 segue。但是,请注意,不应该直接连接到按钮的 segue。我们将以编程方式执行此操作。
例如:
通过 control 将 segue 定义为两个视图控制器之间 - 从第一个场景上方栏中的视图控制器图标拖动到第二个场景:
通过选择 segue 并转到“属性检查器”选项卡,为该 segue 提供故事板标识符:
将按钮(或任何会触发此转场的东西)连接到@IBAction
。
编写一个@IBAction
来执行网络请求,并在完成后以编程方式调用该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
【讨论】:
截图和代码都不错,但似乎与使用NSURLSession
没有任何关系。
@TomHarrington 第 4 步是执行 NSURLSessionTask
。步骤 1-3 概述了我们在步骤 4 中以编程方式执行 segue 所需执行的操作。如果我正确理解了这个问题,OP 会询问如何在执行 segue 之前等待网络响应。
好吧,我想我在所有关于如何设置 segue 的讨论中迷路了。
@TomHarrington - 是的,我解释得不够清楚。只是当人们谈论让 segue 等待某个网络请求时,通常是一个两部分的问题,他们不熟悉异步模式,而且他们不习惯以编程方式执行 segue。我试图添加一些文字来澄清我的观点。以上是关于迅速,我如何才能等到收到服务器响应后再继续?的主要内容,如果未能解决你的问题,请参考以下文章
SwiftUI - 等到 Firestore getDocuments() 完成后再继续