Je veux voir si un objet persiste dans Core Data ou non. Par exemple, j'ai des amis dans les données de base et je les identifie par prénom. Je peux interroger les données de base pour voir si "George" est connu. Si le tableau de l'ensemble de résultats contient plus de zéro objet, je sais que George est là. Mais Core Data charge le tout dans la mémoire, et je veux juste savoir si George est stocké ou non.
Comment pourrais-je le faire de la manière la plus efficace?
Configurez une demande Core Data et, au lieu d'émettre réellement la requête, procédez comme suit:
NSError *error = nil;
NSUInteger count = [managedObjectContext countForFetchRequest:request
error:&error];
if (!error) {
return count;
} else {
return 0;
}
En pratique, la méthode countForFetchRequest:error:
renvoie le nombre d'objets qu'une demande d'extraction donnée aurait renvoyé si elle avait été transmise à executeFetchRequest:error:
.
Modifier: (par Regexident)
Comme Josh Caswell commenté correctement, la bonne façon de gérer les erreurs est soit celle-ci:
if (count == NSNotFound) {
NSLog(@"Error: %@", error);
return 0;
}
return count;
ou ceci (sans enregistrement d'erreur):
return (count != NSNotFound) ? count : 0;
Oui, il y a certainement une meilleure méthode. Configurez une demande de récupération comme d'habitude, mais, au lieu de l'exécuter, demandez simplement le nombre d'objets qu'elle aurait renvoyé si elle avait été transmise à executeFetchRequest: error:
Cela peut être fait en utilisant
- (NSUInteger)countForFetchRequest:(NSFetchRequest *)request error:(NSError **)error;
Quelque chose comme ça:
- (int) numberOfContacts{
NSFetchRequest *request = [[NSFetchRequest alloc] init];
NSManagedObjectContext *managedObjectContext = yourManagedObjectContext;
NSEntityDescription *entity = [NSEntityDescription entityForName:@"Contacts" inManagedObjectContext:managedObjectContext];
[request setEntity:entity];
NSError *error = nil;
NSUInteger count = [managedObjectContext countForFetchRequest:request error:&error];
[request release];
if (!error){
return count;
}
else
return -1;
}
Si le but est de vérifier si l'objet existe, la solution est d'implémenter cette méthode dans votre modèle ami:
-(BOOL)exist
{
NSManagedObjectContext *managedObjectContext = yourManagedObjectContext;
NSEntityDescription *entity = [NSEntityDescription entityForName:@"Friends" inManagedObjectContext:managedObjectContext];
NSFetchRequest *request = [[NSFetchRequest alloc] init];
[request setEntity:entity];
[request setFetchLimit:1];
[request setPredicate:[NSPredicate predicateWithFormat:@"firstName == %@", self.firstName]];
NSError *error = nil;
NSUInteger count = [managedObjectContext countForFetchRequest:request error:&error];
if (count)
{
return YES;
}
else
{
return NO;
}
}
Selon Core Data Documentation , vous ne devez pas continuer à chercher pour voir si des objets existent.
Il existe de nombreuses situations où vous devrez peut-être rechercher des objets existants (objets déjà enregistrés dans un magasin) pour un ensemble de valeurs d'entrée discrètes. Une solution simple consiste à créer une boucle, puis à tour de rôle pour chaque valeur d'effectuer une extraction pour déterminer s'il existe un objet persistant correspondant, etc. Ce modèle n'est pas très évolutif. Si vous profilez votre application avec ce modèle, vous constatez généralement que l'extraction est l'une des opérations les plus coûteuses de la boucle (par rapport à une simple itération sur une collection d'éléments). Pire encore, ce modèle transforme un problème O(n)) en problème O (n ^ 2).
Modifier le 16 mars :
Je ne suis pas un expert db, mais comme les gens demandent une solution plus efficace, considérez cet ensemble:
set1 = [Apple, orange, banana, pineapple, lettuce]
Nous voulons savoir si [mango, Apple, grape]
fait partie de cet ensemble.
Les documents nous disent de ne pas parcourir [mangue, pomme, raisin] et d'interroger la base de données à la recherche de chaque article à tour de rôle, car c'est lent.
Considérez cette solution:
Hachez les ensembles côté serveur:
hash([mango, Apple, grape]) = 234095dda321affe...
Vous pouvez ensuite contourner complètement Core Data en demandant au serveur si quelque chose a changé. Si les ensembles sont différents, vous pouvez ensuite vider les objets dans un contexte d'objet géré et effectuer une sauvegarde en bloc.
Si vous cherchiez vraiment à voir si chaque objet à son tour faisait partie de l'ensemble, vous pourriez faire une recherche basée sur une caractéristique indexée, telle que "fruit avec peau".
Mettre à jour vers Swift 5:
func checkIfItemExist(id: Int, type: String) -> Bool {
let managedContext = CoreDataStack.sharedInstance.persistentContainer.viewContext
let fetchRequest = NSFetchRequest<NSManagedObject>(entityName: "DetailsEntity")
fetchRequest.fetchLimit = 1
fetchRequest.predicate = NSPredicate(format: "id == %d" ,id)
fetchRequest.predicate = NSPredicate(format: "type == %@" ,type)
do {
let count = try managedContext.count(for: fetchRequest)
if count > 0 {
return true
}else {
return false
}
}catch let error as NSError {
print("Could not fetch. \(error), \(error.userInfo)")
return false
}
}