Das Problem, auf das ich stoße, ist folgendes:
Ich habe ein UITableView
, das ich mit Daten aus einem NSFetchedResultsController
füttere, das ungefähr 6000 Zeilen aus den Kerndaten abruft. % Co_de% von fetchBatchSize
wird auf 20 gesetzt und wenn ich NSFetchRequest
nicht anwende, ist das Fetch schnell genug, um den UI-Thread nicht zu blockieren.
Allerdings muss ich diese Zeilen alphabetisch sortiert anzeigen, für die ich den folgenden NSSortDescriptor verwende:
%Vor%Und wenn sich die Dinge ändern, dauert der Abrufvorgang jetzt etwa 3 Sekunden, weil die 6000 Zeilen sortiert werden. Offensichtlich ist die Benutzeroberfläche während dieser Sekunden blockiert und die Benutzererfahrung ist schrecklich.
Ich weiß, dass ich den Abruf in einem Hintergrundthread machen und dann zu Objekt-IDs an den Hauptthread übergeben kann, aber in diesem Fall könnte ich immer noch NSSortDescriptor
im Hauptthread verwenden (ich verwende es auch dazu) Änderungen an den Daten beobachten)?
Ich habe auch NSFetchedResultsController
das Attribut, nach dem ich sortiere, aber das optimiert nur die Suche und nicht die Leistung.
Irgendwelche Ideen würden sehr geschätzt, danke!
Zunächst wird NSFetchedResultsController normalerweise im Hauptthread verwendet. Und es unterstützt nicht Hintergrund holen bis jetzt Apple Release iOS 6.
Wenn Sie also den performFectch von NSFetchedResultController aufrufen, müssen Sie den Hauptthread eine Weile "blockieren". Wir möchten jedoch, dass die Zeit minimal ist.
(Soweit ich mich erinnern konnte, müssen Sie einen Sortierdeskriptor auf NSFetchedResultController setzen. Also bin ich mir nicht sicher, wie Sie es geschafft haben, ohne einen Sortierdeskriptor zu setzen. Schauen Sie sich die Klassenreferenz an)
Ich bin mir nicht sicher, ob Sie SQLite Store verwenden. Wenn dem so ist, kann ich Ihre Arbeit als Sortierer kaum glauben. (Werfen Sie einen Blick auf Core Data Programming Guide: Fehlersuche). Wenn nicht, halte so viele Daten im Speicher wäre keine gute Idee
Endlich haben wir den Punkt erreicht, warum es langsam ist. Diese Sortierung unter Verwendung von "localizedCaseInsensitiveCompare:" führt zu einem langsamen Abruf, da die Unicode-Zeichenfolge im Vergleich langsam ist. (erwähnt in WWDC 2010 Core Data Performance auf dem iPhone).
Wie viele andere Anwendungen sollten Sie ein Nicht-Unicode-String-Feld / -Eigenschaft basierend auf Ihrem "optionText" erstellen und basierend auf dieser Nicht-Unicode-String-Eigenschaft sortieren.
Wie wäre es mit der batchSize
-Eigenschaft von NSFetchRequest?
Wenn Sie eine Stapelgröße ungleich Null festlegen, wird die Auflistung der zurückgegebenen Objekte zurückgegeben Wenn der Abruf ausgeführt wird, wird in Stapel aufgeteilt. Wenn das Holen ist ausgeführt, wird die gesamte Anfrage ausgewertet und die Identitäten von allen übereinstimmende Objekte, die aufgezeichnet wurden, aber nicht mehr als die Daten von batchSize-Objekten wird zu einem bestimmten Zeitpunkt aus dem persistenten Geschäft geholt. Das Array Von der Ausführung der Anfrage zurückgegeben wird ein Proxy-Objekt, das Transparente Fehlchargen bei Bedarf. (In Datenbankbegriffen ist dies ein In-Memory-Cursor.)
Ich führe einen Batch im Hintergrund in einer NSOperation aus, die einen separaten NSManagedObjectContext verwendet. In regelmäßigen Abständen speichere ich den zweiten Kontext, der eine Benachrichtigung auslöst, um meinen Haupt-NSManagedContext zu aktualisieren, an den mein NSFetchedResultsController angeschlossen ist.
Vielleicht könnte eine ähnliche Technik auf Ihren Abruf angewendet werden
Hier ist ein Kakao ist meine Freundin Artikel darüber:
und das Verfahren wird auch im Leitfaden für die Kerndatenprogrammierung "Importieren in Stapeln"
erwähntDie Verwendung eines Caches würde wahrscheinlich zu einer besseren Leistung führen.
Ich habe das gleiche Problem und habe erkannt, dass der Abruf im ersten Aufruf mehr als 3 Sekunden benötigt, aber den Abruf zweimal durchführt, zeigt sofort seine Ergebnisse.
Das Anzeigen von 6000 Zeilen in einer Tabelle ist möglicherweise nicht die beste Lösung für die Benutzererfahrung. Vielleicht solltest du vorher eine Filtertabelle hinzufügen. Ähnlich wie die Gruppen im Adressbuch. Dies würde möglicherweise zu einer besseren Benutzererfahrung führen, wenn Sie die Anzahl der Zeilen pro Filteroption auf eine handlichere Zahl reduzieren können. Dies würde Ladezeit und Scrollzeit reduzieren.
Ich weiß nicht, welche Art von Daten Sie anzeigen, daher gibt es vielleicht keine andere Möglichkeit, als alle in einer langen Liste anzuzeigen. Für Personen können Sie Optionen für Geschlecht und Altersgruppen hinzufügen. Für Autos können Sie einen Filter nach Marke und Modellen hinzufügen ....
Haben Sie versucht, die Methode performFetch: im Hintergrund auszuführen, entweder mit
%Vor%oder
%Vor%Tags und Links core-data background sorting nsfetchedresultscontroller