insert de lot iOS CoreData?
Dans mon application iPhone, je dois insérer ~2000 enregistrements dans les données de base avant que l'utilisateur puisse utiliser toutes les fonctionnalités de l'application. Je charge les enregistrements dans CoreData à partir d'un fichier JSON local. Ce processus prend beaucoup de temps(2,5+ minutes), mais ne doit se produire qu'une seule fois (ou chaque application ~10 s'ouvre pour obtenir des données mises à jour).
Y a-t-il un insert de lot pour les données de base? Comment puis-je accélérer ce processus d'insertion?
Si Je ne peux pas l'accélérer en utilisant les données de base, quels sont les autres options recommandées?
3 réponses
Consultez le chapitre Importation efficace des données du Guide de programmation des données de base.
J'ai actuellement les mêmes problèmes que vous, seulement j'insère 10000 objets et cela prend environ 30s, ce qui est encore lent pour moi. Je fais un [managedobjectcontext save] sur chaque 1000 objets gérés insérés dans le contexte (en d'autres termes, ma taille de lot est de 1000). J'ai expérimenté avec 30 tailles de lots différentes (de 1 à 10000), et 1000 semble être la valeur optimale dans mon cas.
Je cherchais la réponse à une question similaire quand je suis tombé sur celui-ci. La réponse de @VladimirMitrovic était utile à l'époque pour savoir que je ne devrais pas enregistrer le contexte à chaque fois, mais je cherchais aussi un exemple de code.
Maintenant que je l'ai, je vais fournir le code ci-dessous afin que d'autres personnes puissent voir à quoi cela pourrait ressembler de faire un insert de lot.
// set up a managed object context just for the insert. This is in addition to the managed object context you may have in your App Delegate.
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. Your implementation may vary.
autoreleasepool { // auto release objects after the batch save
let array: Array<MyManagedObject>? = getNextBatchOfObjects() // The MyManagedObject class is your entity class, probably named the same as MyEntity
if array == nil { break } // there are no more objects to insert so stop looping through the batches
// insert new entity object
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()
}
}
Objectif-C
Version Pour @Suragch anwser
NSManagedObjectContext * MOC = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
MOC.persistentStoreCoordinator = YOURDB.persistentStoreCoordinator;
[MOC performBlock:^{
// DO YOUR OPERATION
}];