在 swift 中,如何才能等到收到服务器响应后再继续? [英] In swift, how can I wait until a server response is received before I proceed?

查看:41
本文介绍了在 swift 中,如何才能等到收到服务器响应后再继续?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如果我从服务器得到某个响应,我只想执行一个 segue.在 swift 中,我如何才能等到收到回复才能继续?

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?

推荐答案

最重要的是,你不需要等待"响应,而是简单地指定响应到来时你想要发生的事情.例如,如果您想在完成某些网络请求时执行 segue,您应该使用完成处理程序模式.

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.

这里的问题是您可能习惯于将 UI 控件连接到 Interface Builder 中的 segue.在我们的例子中,我们不想这样做,而是想执行网络请求,然后让它的完成处理程序以编程方式调用 segue.因此,我们必须创建一个可以以编程方式执行的 segue,然后将您的按钮连接到一个 @IBAction 来执行网络请求,并在适当的情况下以编程方式执行 segue.但是,请注意,不应该直接连接到按钮上.我们将以编程方式执行此操作.

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.

例如:

  1. 通过control-从第一个场景上方栏中的视图控制器图标拖动到第二个场景来定义两个视图控制器之间的转场:

  1. 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:

通过选择 segue 并转到属性检查器"选项卡,为该 segue 提供故事板标识符:

Give that segue a storyboard identifier by selecting the segue and going to the "Attributes Inspector" tab:

将按钮(或将触发此转场的任何东西)连接到 @IBAction.

Hook up the button (or whatever is going to trigger this segue) to an @IBAction.

编写一个 @IBAction 来执行网络请求,并在完成后以编程方式调用该 segue:

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
}

这篇关于在 swift 中,如何才能等到收到服务器响应后再继续?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆