2016-08-04 18 views
2
kommuniziert

Ich sammelte JSON Daten von einer API und kann mein Array (Klasseninstanzvariable) initialisieren, aber nach dem Block werden Daten aus Array zerstört. Wie kann ich Daten aus dem Aufgabenblock zurückgeben, die zur Initialisierung meines Arrays verwendet werden können?Wie das Ergebnis von NSURLRequest zurück an die Klasse

override func viewDidLoad() { 
    // var movies=[Movie]() 

    let requestURL: NSURL = NSURL(string: "https://yts.ag/api/v2/list_movies.json")! 
    let urlRequest: NSMutableURLRequest = NSMutableURLRequest(URL: requestURL) 
    let session = NSURLSession.sharedSession() 
    let task = session.dataTaskWithRequest(urlRequest) { 
     (data, response, error) -> Void in 

     let httpResponse = response as! NSHTTPURLResponse 
     let statusCode = httpResponse.statusCode 
     if (statusCode == 200) { 
      print("File downloaded successfully.") 
      do { 
       let jsonYts = try NSJSONSerialization.JSONObjectWithData(data!, options:.AllowFragments) 

       let jsonDataTag = jsonYts["data"] 
       let jsonMovie = jsonDataTag!!["movies"]! 

       let movies = [Movie].fromJSONArray(jsonMovie as! [JSON]) 

       // self.moviesList = movies as! [Movie] // this is my array. I want to add data to it 

       for data in self.moviesList { 
        // print(data.title) 
       } 
      } catch { 

      } 
     } 
    } 

    task.resume()  
} 
+5

Beispiel in meiner Antwort hier nehmen: http://stackoverflow.com/questions/37340967/json-parsing-swift-array-has-no-value-outside-nsurlsession – Moritz

Antwort

0

Asynchrone Methoden kehren nicht zur aufrufenden Funktion zurück, weil sie nicht direkt an erster Stelle aufgerufen werden. Sie werden in einer Aufgabenwarteschlange platziert, die später aufgerufen wird (in einem anderen Thread!). Es ist das Schwierigste für Neulinge, die asynchrone Programmierung beherrschen. Ihre asynchrone Methode muss eine Klassenvariable mutieren. So werden Sie haben:

class MyContainer: UIViewController { 
    var myInstanceData: [SomeObject] // In your case moviesList 

    func startAsyncRequest() { // In your case viewDidLoad() 
     // In your case NSMutableURLRequest 
     doSomethingAsynchronous(callback: { [weak self] (result) in 
      // in your case JSON parsing 
      self?.myInstanceData = parseResult(result) // share it back to the containing class 
      // This method returns nothing; it is not called until well 
      // after startAsyncRequest() has returned 
     }) 
    } 
} 

Sobald der Rückruf abgeschlossen ist, myInstanceData zu allen anderen Methoden in der Klasse zur Verfügung steht. Ist das als allgemeines Muster sinnvoll?

Danach müssen Sie das Material erfahren:

Swift performSegueWithIdentifier not working

Um auf dem Ihr Rückruf läuft das Ergebnis wieder in die Benutzeroberfläche aus dem Hintergrund-Thread zu bekommen.

Nachtrag einen zweiten Blick nach Ihrer Frage für Klarheit bearbeiten, es scheint, dass Sie bereits wissen, aber Sie haben die richtige Zeile auf Kommentar, und wenn Sie es in setzen, die Dinge einfach funktionieren, dass Die Filme werden nicht zerstört, sondern in der Klasseneigenschaft moviesList aufgenommen.

  // self.moviesList = movies as! [Movie] // this is my array. I want to add data to it 

Warum nicht einfach wieder aktivieren? Vielleicht ist das eigentliche Problem: Meinst du zu append statt zu überschreiben, vielleicht? Dann kann die Antwort so einfach sein wie:

self.moviesList += movies as! [Movie] 
+0

Ich denke, die Frage als phrasiert ist irreführend und zieht in zwei Richtungen, also bitte klären, auf welchem ​​Teil von dem oben genannten Antwort löst es tatsächlich auf. – BaseZen

-1

Sie können nur „SwiftyJson“ verwenden, um die Antwort von der API zu behandeln, wenn es JSON-Daten zurückgibt; Wenn XML verwendet wird, verwenden Sie "SWXMLHash". Sie sind beide Pods (Bibliotheken), die entworfen wurden, um die Antwort von ihren jeweiligen Formaten zu verarbeiten.

Installation help for SwiftyJson. Wenn Sie noch Probleme haben, kommentieren Sie unten.

An diesem Punkt können Sie SwiftyJson einfach importieren und verwenden.

Let response jedes Objekt sein, und nehmen wir Ihre JSON-Daten in diesem Format ist:

{"text": { 
     "data": "Click Here", 
     "size": 36, 
     "style": "bold", 
     "name": "text1", 
     "hOffset": 250, 
     "vOffset": 100, 
     "alignment": "center" 
    } 
} 

Dann können Sie einfach Code schreiben, wie diese

func response(data){ 

    let dt = JSON(data : data) // the second data is the response from api 

    response = dt.object // for accessing the values as object from json format 

    let style = response["text"]["data"]!! as? String // style = "bold" 

    let n = response["text"]["name"]!! as? String  // n = "text1" 

    let size = response["text"]["hOffset"]!! as? Int // size = 250 
} 


// Done !! Easy.. if you guys need help or snapshots for the same do comment..