2015-06-13 9 views
11

In der Hauptansicht meiner App habe ich eine Tabellenansicht und zwei Prototyp-Zellen. Ich habe die Übergänge für jede Zelle mit dem Storyboard konfiguriert. Im View-Controller überschreibe ich prepareForSegue, um Informationen über die ausgewählte Zelle an die Zielansicht zu übergeben.iOS-Segment für viele Sekunden einfrieren, bevor neue Ansicht angezeigt wird

Die Zielansicht ist nicht besonders komplex und erfordert sicher keine schwere Verarbeitung zum Laden.

DAS PROBLEM

Wenn ich in der Hauptsteuerung für das erste Mal auf einer Zelle tippen, wird die Zielansicht nach einer langen Verzögerung, von 5 bis 40 Sekunden.

EDIT # 2: nachfolgenden Taps sind in der Regel schneller

Beachten Sie, dass:

  • Wenn ich auf der gleichen Zelle tippen Sie erneut vor die Zielansicht erschienen ist, dies die Zielansicht auslöst sofort erscheinen.
  • Wie oben, aber das Tippen auf eine andere Zelle führt dazu, dass die Ansicht sofort erscheint, aber mit den Daten aus der ersten Zelle.
  • Wie oben, aber das Antippen eines anderen Steuerelements (ohne zugeordnete Segmente) löst die sofortige Anzeige der Zielansicht aus.
  • Nachfolgende "Taps" weisen im Allgemeinen weniger Verzögerung auf.
  • Der Time Profiler - für das, was ich sehen kann - zeigt, dass während dieser vielen Sekunden Verzögerung absolut nichts passiert.
  • ich verschiedene Arten von segues versucht, aber es machte keinen Unterschied
  • Eine Show wenig println, die die folgende Sequenz von Ereignissen:

    • in der Hauptansicht wird prepareForSegue ausgeführt (keine Verzögerungen)
    • dann das Ziel viewDidLoad ausgeführt (keine Verzögerungen)
    • ... lange Verzögerung ...
    • die Sammlung und Tabellenansichten des in den tination Controller startet den Aufruf der datenquellenbezogenen Methoden, um die Daten vom Controller zu holen.
    • der Blick erscheint schließlich (mit einer unerwünschten Animation, BTW, aber das ist ein anderes Problem)

Von dem, was ich zu diesem Thema gelesen habe, vermute ich das Problem möglicherweise auf einige der in Beziehung steht über Operationen in einem Hintergrundthread.

Irgendeine Idee, was ich falsch machen könnte?

EDIT # 1: hinzugefügt einige Code

in der Hauptansicht-Controller haben die segues gewesen Link, um die Storyboard (CTRL-Drag die beiden Prototyp-Zellen in die Zielansicht) verwenden.

Der Code sieht ein bisschen wie folgt:

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) 
{ 
    var assetIndex = assetsTable.indexPathForSelectedRow()?.row 

    println("prepare for segue - start: \(assets[assetIds[assetIndex!]]!.Name)") 

    if let destination = segue.destinationViewController as? AssetThingsListViewController 
    { 
     destination.bundlesRepository = bundlesRepository! 
     destination.asset = assets[assetIds[assetIndex!]] 
    } 

    println("prepare for segue - end") 
} 

EDIT # 3 ich ein Beispielprojekt auf zur Verfügung gestellt haben BitBucket

+1

Ich denke, das ist ein Fehler. Das passierte mir jedes Mal, wenn ich zum ersten Mal eine Überfahrt machte. Beginne mit iOS 8. –

+0

Hast du versucht, die App im Freigabemodus auszuführen? Ich schätze, Sie werden dieses Verhalten nur im Debug-Modus sehen. –

+0

Leider passiert es auch weiterhin im Freigabemodus. –

Antwort

10

Ich habe Ihr Projekt überprüft. Und obwohl ich auch sonst nichts finden konnte, vermute ich auch, dass es ein Problem mit Threading ist.

ich es geschafft, das Problem zu beheben, indem Sie einen Delegaten für die tableview und präsentieren den neuen Controller in Code Implementierung:

func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) { 

    let destination = storyboard?.instantiateViewControllerWithIdentifier("BuilderToysListViewController") as! BuilderToysListViewController 
    destination.botsRepository = botsRepository! 
    destination.builder = builders[builderIds[indexPath.row]] 

    dispatch_async(dispatch_get_main_queue(), {() -> Void in 
     self.presentViewController(destination, animated: true) {() -> Void in 

     } 
    }) 

} 

Hinweis Sie den Satz haben die View-Controller-Storyboard-ID: BuilderToysListViewController und ebenso über die Tableview Delegat . Vergessen Sie nicht, die Übergänge zu entfernen.

Am Ende die Ansicht in der neuen Ansicht-Controller verwenden diesen Code dissmis:

@IBAction func backButton(sender: AnyObject) 
{ 
    dismissViewControllerAnimated(true, completion: {() -> Void in 

    }) 
//  performSegueWithIdentifier("segueToysByBuilder", sender: nil)   

} 

Dies würde ermöglichen es Ihnen, die Ansicht, anstatt zu Unrecht die Schaffung eines neuen ordnungsgemäß zu schließen.

+0

Danke @pteofil. Es scheint, dass ich einen iOS 8 Bug getroffen habe. https://forums.developer.apple.com/message/12349 –

+0

Kann jemand erklären, was der oben genannte Code tut? Ich habe das gleiche Problem, wenn einige Taps verzögert werden und andere normal sind. Ich erkenne das BotsRepository oder den Versandcode nicht und möchte Code nicht in meine App integrieren, ohne ihn zu verstehen. Allerdings möchte ich eine App, die keine frustrierenden Verzögerungen hat !! Kann jemand erklären, was dieser Code macht/warum er hilft? Vielen Dank! @pteofil –

+0

Der obige Code präsentiert den neuen Controller einfach im Code, wenn eine Zelle angezapft wird, anstatt Dinge nur im Storyboard festzulegen. In diesem Fall können Sie den Teil überspringen, der das botsRepository und den Builder festgelegt hat.Sie sind nur Eigenschaften des jeweiligen Controllers, der präsentiert wird. Das 'dispatch_async' wird jedoch benötigt, um einen Code in einem bestimmten Thread aufzurufen. Alle Änderungen an der Benutzeroberfläche müssen im Hauptthread vorgenommen werden. Und normalerweise ist dies der Fall bei Dingen, die im Storyboard eingerichtet sind. Aber es gibt Fehler, und in diesem Fall präsentiere ich den neuen Controller auf dem Hauptthread zur Sicherheit – pteofil

0

Schwer zu sagen, es sei denn, Sie Ihren Code schreiben, die auf die reagiert Tippen Sie auf die Zelle und präsentieren Sie den neuen View-Controller.

Eine häufige Ursache für lange Verzögerungen bei UI-Änderungen (oder wenn die UI-Änderung nie erfolgt) versucht, UI-Änderungen von einem Hintergrundthread vorzunehmen. Ist es möglich, dass Ihr Code, der das Segment aufruft, in einem anderen Thread ausgeführt wird? Sie können dies leicht erkennen, indem Sie einen Haltepunkt für diesen Code festlegen und die Thread-Nummer beobachten, wenn sie bricht. Wenn die Thread-Nummer 0 ist, wird der Haupt-Thread ausgeführt. Wenn es eine andere Thread-Nummer ist, ist das dein Problem.

+0

Auch habe ich festgestellt, dass nachfolgende "taps" sind ** in der Regel ** ohne Verzögerung, aber ich habe gerade Fälle von konsequenten Verzögerungen in nachfolgenden auch gesehen. –