2016-07-27 49 views
-1

Ich möchte nur einen Übergang ausführen, wenn ich eine bestimmte Antwort vom Server bekomme. Wie schnell kann ich warten, bis ich eine Antwort bekomme?In swift, wie kann ich warten, bis eine Serverantwort eingegangen ist, bevor ich fortfahre?

+7

Verwendung completionHandler: – Khundragpan

+0

http://stackoverflow.com/questions/ 8427836/how-to-make-program-warten-für-asynchrone-nsurlconnection-to-finish-vor-proce –

+1

Sie wollen fast nie * warten * aktiv sein, da das Ihren aktuellen Thread blockiert. – luk2302

Antwort

1

Unterm Strich warten Sie nicht auf die Antwort, sondern geben einfach an, was bei der Antwort geschehen soll. Wenn Sie zum Beispiel einen Übergang durchführen möchten, nachdem eine Netzwerkanforderung ausgeführt wurde, Sie sollten das Beendigungshandlermuster verwenden.

Das Problem hier ist, dass Sie wahrscheinlich daran gewöhnt sind, Ihre UI-Steuerung nur an ein Segment im Interface Builder anzuhängen. In unserem Fall wollen wir das nicht machen, sondern wir wollen die Netzwerkanforderung ausführen und dann den Programmablauf von seinem Abschluss-Handler aufrufen lassen. Wir müssen also ein Segment erstellen, das programmgesteuert ausgeführt werden kann, und dann Ihre Schaltfläche an eine @IBAction anhängen, die die Netzwerkanforderung ausführt und, falls zutreffend, das Segment programmgesteuert ausführt. Aber, beachten Sie, es sollte keine Verbindung direkt mit dem Button verbunden sein. Wir machen das programmatisch.

Zum Beispiel:

  1. die segue definieren zwischen den beiden Controllern Ansicht von Steuer -dragging aus dem View-Controller-Symbol in der Leiste über der ersten Szene zu der zweiten Szene sein:

    enter image description here

  2. können, dass der Übergang von der Auswahl und gehen auf die „Attribute Inspector“ Tab ein Storyboard-Kennung segue:

    enter image description here

  3. die Schaltfläche Schalt (oder was auch immer wird diesen Übergang triggern) zu einem @IBAction.

    enter image description here

  4. eine @IBAction schreiben, die Netzwerkanforderung und nach Abschluß durchführt, ruft diese programmatisch segue:

    @IBAction func didTapButton(sender: AnyObject) { 
        let request = NSURLRequest(...)  // 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 = NSURLSession.sharedSession().dataTaskWithRequest(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 { 
          dispatch_async(dispatch_get_main_queue()) { 
           waitingView.removeFromSuperview() 
          } 
         } 
    
         // make sure there wasn't an error; you'll undoubtedly have additional 
         // criteria to apply here, but this is a start 
    
         guard data != nil && error == nil else { 
          print(error) 
          return 
         } 
    
         // parse and process the response however is appropriate in your case, e.g., if JSON: 
         // 
         // guard let responseObject = try? NSJSONSerialization.JSONObjectWithData(data!, options: []) else { 
         //  // handle parsing error here 
         //  return 
         // } 
         // 
         // // do whatever you want with the parsed JSON here 
    
         // do something with response 
    
         dispatch_async(dispatch_get_main_queue()) { 
          self.performSegueWithIdentifier("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 
    } 
    
+0

Die Screenshots und der Code sind gut, aber sie scheinen nichts mit 'NSURLSession' zu tun zu haben. –

+0

@ TomHarrington Schritt 4 ist die Durchführung der 'NSURLSessionTask'. In den Schritten 1-3 werden die Schritte beschrieben, die Sie zum programmatischen Ausführen des Programmschritts in Schritt 4 ausführen müssen. Wenn ich die Frage richtig verstanden habe, fragte das OP, wie auf die Netzwerkantwort gewartet werden soll, bevor das Segment ausgeführt wird. – Rob

+0

OK, ich glaube, ich habe mich in dem ganzen Gerede darüber verloren, wie man ein Segment aufstellt. –