Es gibt ein paar Dinge, die Sie ändern sollen:
- Erstellen Ihnen einen separaten
NSPrivateQueueConcurrencyType
Objektkontext verwaltet und es Ihre Einsätze asynchron tun.
- Speichern Sie nicht nach dem Einfügen jedes einzelnen Entitätsobjekts. Fügen Sie Ihre Objekte in Stapeln ein und speichern Sie dann jeden Stapel. Eine Stapelgröße kann etwa 1000 Objekten entsprechen.
- Verwenden Sie
autoreleasepool
und reset
, um die Objekte im Speicher nach jedem Einfügen und Speichern zu löschen.
Hier ist, wie dies funktionieren könnte:
let managedObjectContext = NSManagedObjectContext(concurrencyType: NSManagedObjectContextConcurrencyType.PrivateQueueConcurrencyType)
managedObjectContext.persistentStoreCoordinator = (UIApplication.sharedApplication().delegate as! AppDelegate).persistentStoreCoordinator // or wherever your coordinator is
managedObjectContext.performBlock { // runs asynchronously
while(true) { // loop through each batch of inserts
autoreleasepool {
let array: Array<MyManagedObject>? = getNextBatchOfObjects()
if array == nil { break }
for item in array! {
let newEntityObject = NSEntityDescription.insertNewObjectForEntityForName("MyEntity", inManagedObjectContext: managedObjectContext) as! MyManagedObject
newObject.attribute1 = item.whatever
newObject.attribute2 = item.whoever
newObject.attribute3 = item.whenever
}
}
// only save once per batch insert
do {
try managedObjectContext.save()
} catch {
print(error)
}
managedObjectContext.reset()
}
}
Anwendung dieser Grundsätze hielt meine Speicherauslastung gering und machte auch die Masse schneller einsetzen.
Weiterführende Literatur
- Effizientes Importieren von Daten (alte Apple-docs Verbindung unterbrochen wird. Wenn Sie es nicht finden, bitte helfen Sie mir etwas hinzufügen.)
- Core Data Performance
- Core Data (Hauptpost)
aktualisieren
Die obige Antwort komplett neu geschrieben wird. Danke an @Mundi und @MartinR in den Kommentaren für einen Hinweis auf einen Fehler in meiner ursprünglichen Antwort. Und danke an @JodyHagins in this answer für das Verständnis und die Lösung des Problems.
Es scheint, dass Sie in Ihrem Code den gleichen Kontext verwalteter Objekte verwenden, nicht einen neuen. – Mundi
Der Kontext des verwalteten Objekts wird in meinem obigen Beispiel in jeder while-Schleife neu erstellt. Die "while" -Schleife stellt einen Stapel von Einfügungen dar, sodass ein einzelner Stapel den gleichen Kontext für verwaltete Objekte verwendet, der nächste Stapel jedoch einen neuen erstellt. Mein Problem in der Vergangenheit war, dass ich den Kontext zu einer Klasseneigenschaft gemacht und nie geändert habe. – Suragch
@Suragh: Das hängt davon ab, wie die Eigenschaft 'managedObjectContext' im Anwendungsdelegaten implementiert wird, aber die" normale "Implementierung ist eine faule Eigenschaft, die den Kontext einmal für die Lebensdauer der App erstellt. In diesem Fall verwenden Sie denselben Kontext wie Mundi sagte. –