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?

23
demandé sur binnyb 2010-11-10 18:13:03

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.

28
répondu Vladimir Mitrovic 2016-04-14 11:43:07

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()
    }
}
5
répondu Suragch 2017-05-23 11:47:12

Objectif-C

Version Pour @Suragch anwser

NSManagedObjectContext * MOC = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
MOC.persistentStoreCoordinator = YOURDB.persistentStoreCoordinator;
[MOC performBlock:^{ 
   // DO YOUR OPERATION
 }];
0
répondu Abhishek Thapliyal 2017-03-23 08:39:48