2016-04-08 9 views
0

Ich meine durch "langsam", dass die Callback-Art warten auf den Remote-Server zu Timeout wirksam (Aufruf eines vimeo Feed, Parsing und dann Anzeige von uiviews in der Szene)iOS9 // NSURLSession dataTaskWithURL sehr "langsam"

Ich verstehe meist nicht, wie es funktioniert. Ich möchte meine Ansicht innerhalb der Callback aufgefüllt werden, sobald die Antwort

Mit den nachfolgenden Code zurückgegeben wird (rubymotion, aber Sie könnten auf die Idee kommen):

session = NSURLSession.sharedSession 
url = NSURL.URLWithString(ALBUMS_URL) 
downloadTask = session.dataTaskWithURL(url, completionHandler: lambda { |data, response, error| 
    # 'puts' prints the result in the console, you get it as soon as the response arrives 
    puts data 
    # testing with a simple view 
    v = UIView.alloc.initWithFrame(CGRectMake(0,0,@width/2,200)) 
    v.backgroundColor = UIColor.blackColor 
    self.view.addSubview v # ==> takes forever to effectively appear on the scene 
}) 

Ich landete Einstellung es im Hauptthread mit dem folgenden

NSURLSession.sessionWithConfiguration(
    NSURLSessionConfiguration.defaultSessionConfiguration, 
    delegate:nil, 
    delegateQueue: NSOperationQueue.mainQueue 
) 

Etwas anderes sollte verwendet werden, um diese Art von Aufgaben zu erledigen? Gibt es eine Möglichkeit, die Ansicht zu "aktualisieren", um sie zu aktualisieren? vollständig ankommen

Vielen Dank für Ihre Hilfe auf dieser

+1

Das ist nicht genug Informationen, um deine Frage zu beantworten. – trojanfoe

+0

@trojanfoe bitte sagen Sie mir, wie Sie genauer sein können. Im Grunde, ohne es in den Hauptthread zu setzen, dauert die Ansicht 30 Sekunden, um aktualisiert zu werden – Ben

+0

@trojanfoe bearbeitet – Ben

Antwort

1

Der Grund, dass Ihre Benutzeroberfläche so lange dauert, ist nicht, weil die Operation so lange dauerte, sondern weil die NSURLSessionDataTask in einem Hintergrundthread endet. Wie Sie vielleicht wissen, sollten Sie keine UI-Änderungen von einem Hintergrundthread vornehmen, sondern nur den Hauptthread.

Ihre Lösung, den Callback der gesamten URL-Sitzung in die Hauptwarteschlange zu stellen, "löst" dieses Problem, aber nicht den richtigen Weg, da Sie jetzt Netzwerkbetrieb in der Hauptwarteschlange durchführen, die für Dinge so wenig wie möglich sein sollte kann im Hintergrund (wie Netzwerkoperationen) erfolgen.

Um dies zu beheben, müssen Sie die Netzwerkvorgänge im Hintergrundthread ausführen und dann die UI-Änderungslogik im Hauptthread aufrufen. Sie können eine einfache dispatch_async() telefonierte um einen Block zu bilden, die die Benutzeroberfläche aktualisiert, so (sorry, ich bin mit RubyMotion nicht vertraut, so dass ich dies in Objective-C zu schreiben):

// in the callback for NSURLSessionDataTask: 
NSLog(@"%@", data); 

// Dispatch the UI-related logic as a block on the main-thread 
dispatch_async(dispatch_get_main_queue(), ^{ 
    UIView *v = [[UIView alloc] initWithFrame:CGRectMake(0,0,width/2,200)]; 
    v.backgroundColor = [UIColor blackColor]; 
    [self.view addSubview:v]; 
}); 
1

Es klingt wie es 30 Sekunden, die Daten stattfindet. Um die Daten schneller zu präsentieren, müssen Sie wahrscheinlich einen Delegaten verwenden, die Daten nach dem Empfang eines Chunks abrufen, einen Parser verwenden, der mit teilweise empfangenen Daten umzugehen weiß, und dann weitere Daten zu Ihrer UI hinzufügen Sie erhalten zusätzliche Daten.

Edit: Irgendwie, als ich das zuvor beantwortet habe, verpasste ich die Tatsache, dass dies nur fehlgeschlagen, wenn nicht auf einem Hauptthread ausgeführt. Wie der andere Kommentator bemerkt, müssen Sie müssen entweder die Aufgabe auf den Haupt-Thread oder verwenden Sie dispatch_async innerhalb des Blocks, so dass die Label-Änderungen auf dem Haupt-Thread ausgeführt werden. Andernfalls wird die Benutzeroberfläche nicht aktualisiert, bis ein anderer Code, der im Hauptthread ausgeführt wird, eine Neuzeichnung der betreffenden Ansicht verursacht.