在swift中,我怎么能等到收到服务器响应才能继续?

时间:2016-07-27 15:52:20

标签: swift server segue response completion

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

1 个答案:

答案 0 :(得分:1)

最重要的是,您不要“等待”响应,而是简单地指定响应进入时您想要发生的事情。例如,如果您想在某些网络请求完成时执行segue,应该采用完成处理程序模式。

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

例如:

  1. 通过 control 定义两个视图控制器之间的segue - 从第一个场景上方的条形图中的视图控制器图标拖拽到第二个场景:

    enter image description here

  2. 通过选择segue并转到“Attributes Inspector”选项卡,为该segue提供一个故事板标识符:

    enter image description here

  3. 将按钮(或任何将触发此segue的内容)连接到@IBAction

    enter image description here

  4. 编写一个执行网络请求的@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
    }