39 votes

Comment récupérer uniquement le premier enregistrement dans Core Data ?

J'utilise Core Data et je veux seulement récupérer le premier enregistrement de mon jeu de données, est-ce possible ?

75voto

Tim Points 33042

Vous pouvez utiliser le setFetchLimit: sur NSFetchRequest pour limiter le nombre d'enregistrements récupérés. Ainsi, si vous ne voulez que le premier enregistrement :

// Given some existing NSFetchRequest *request and NSManagedObjectContext *context:
[request setFetchLimit:1];
NSError *error;
NSArray *results = [context executeFetchRequest:request error:&error];

Notez que l'appel à executeFetchRequest:error: retournera toujours un NSArray ; vous devrez toujours extraire le premier objet du tableau avant de pouvoir l'utiliser, même s'il s'agit d'un tableau de taille 1.

Une autre méthode, moins efficace : Selon le type de magasin, la limitation de l'extraction peut accélérer considérablement les performances. Cependant, si ce n'est pas le cas, ou si vous n'êtes pas si préoccupé par les performances, et que vous pourriez utiliser plus de données plus tard, vous pouvez simplement extraire le premier objet du tableau à l'avance :

// Given some existing result NSArray *results:
NSManagedObject *firstManagedObject = [results objectAtIndex:0];

Vous pouvez même le placer dans un autre tableau (pour l'utiliser dans un UITableViewController, par exemple) en procédant comme suit :

// Again, with some NSArray *results:
NSArray *singleObjectResult = [results subarrayWithRange:NSMakeRange(0, 1)];

13voto

Craig McMahon Points 464

Bien sûr, cela dépend en partie de ce que vous entendez par "premier enregistrement". Il se peut que vous deviez non seulement fixer la limite de la recherche à 1, mais aussi trier les résultats de la recherche.

Par exemple, j'ai un tas de User dans ma base de données, et je veux trouver le premier qui a créé un compte. (En supposant que j'ai déjà le modèle de User dont un attribut nommé accountCreatedDate .)

NSEntityDescription *entity = [NSEntityDescription entityForName:@"User" inManagedObjectContext:managedObjectContext];
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"accountCreatedDate" ascending:YES]; // ascending YES = start with earliest date
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];
NSError *error;
NSFetchRequest *request = [[NSFetchRequest alloc] init];
[request setEntity:entity];
[request setSortDescriptors:sortDescriptors];
[request setFetchLimit:1];

NSArray *fetchResults = [managedObjectContext executeFetchRequest:request error:&error];

User *result = nil;

if ([fetchResults count]>0)
    result = [fetchResults objectAtIndex:0];

[request release];
[sortDescriptors release];
[sortDescriptor release];

Si vous ne triez pas les résultats avant de limiter la recherche, il est impossible de savoir quels résultats seront renvoyés "en premier".

2voto

MattDiPasquale Points 23842

J'ai utilisé les catégories Objective-C pour ajouter un NSManagedObject méthode de classe appelée firstInManagedObjectContext: .

Code source

// NSManagedObject+Additions.h

@interface NSManagedObject (Acani)

+ (NSString *)entityName;
+ (NSEntityDescription *)entityInManagedObjectContext:(NSManagedObjectContext *)context;
+ (NSManagedObject *)firstInManagedObjectContext:(NSManagedObjectContext *)context;

@end

// NSManagedObject+Additions.m

#import "NSManagedObject+Additions.h"

@implementation NSManagedObject (Acani)

+ (NSString *)entityName {
    return NSStringFromClass([self class]);
}

+ (NSEntityDescription *)entityInManagedObjectContext:(NSManagedObjectContext *)context {
    return [NSEntityDescription entityForName:self.entityName inManagedObjectContext:context];
}

+ (NSManagedObject *)firstInManagedObjectContext:(NSManagedObjectContext *)context {
    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
    [fetchRequest setEntity:[self entityInManagedObjectContext:context]];
    [fetchRequest setFetchLimit:1];

    NSError *error;
    NSArray *fetchedObjects = [context executeFetchRequest:fetchRequest error:&error];
    [fetchRequest release];
    if (fetchedObjects == nil) {
        NSLog(@"Fetch sender error %@, %@", error, [error userInfo]);
        return nil;
    } else if ([fetchedObjects count] > 0) {
        return [fetchedObjects objectAtIndex:0];
    }
    return nil;
}

@end

Utilisation

Ajoutez ces fichiers à votre projet et assurez-vous de les lier à votre cible. Ensuite, #import "NSManagedObject+Additions.h" dans le .m où vous utilisez l'option firstInManagedObjectContext: méthode de classe.

Appelez-le à partir de n'importe quelle sous-classe concrète (non abstraite) de NSManagedObjectContext . Il suffit de lui passer le NSManagedObjectContext *context à partir duquel il faut récupérer l'objet géré. La méthode détecte le (NSString *)entityName du nom de la classe sur laquelle il est appelé. N'oubliez pas de caster le résultat pour une construction propre (sans avertissements).

Je l'utilise pour une classe d'objets gérés dont je sais que je n'ai qu'une seule instance enregistrée. Si vous avez plus d'une instance sauvegardée, vous pouvez ajouter un fichier NSSortDescriptor comme le suggère @Craig McMahon. Vous pouvez également essayer de trier par objectID au lieu de accountCreatedDate si tous les objets sont créés sur le même périphérique. Je ne suis pas sûr, cependant, que les ID des objets soient ordonnés.

Exemple

Imaginez que vous ayez un Event qui descend de NSManagedObjectContext . Vous pourriez le faire :

Event *event = (Event *)[Event firstInManagedObjectContext:context];

Blocs

Après avoir lu le Tutoriel sur les blocs iOS 4 de Pragmatic Studio j'ai réalisé que ce code pouvait être amélioré et rendu encore plus modulaire en ajoutant une autre fonction, appelée + fetch et l'ajout d'un NSFetchRequestBlock (qui prendrait le fetchRequest comme argument) & NSFetchRequestFailureBlock comme arguments pour personnaliser la demande de récupération et le traitement de l'erreur de demande de récupération, respectivement. Je vous mets au défi de vous attaquer à cela ! :)

0voto

johndpope Points 1485

C'est ma tentative. N.B. L'entité Book hérite de NSManagedObject.

NSPredicate *predicate = [NSPredicate predicateWithFormat: @"isbn ==9780786660506"];

Book *book = (Book*) [CoreDataHelper getEntityFromFetchedResultsController:@"Book" :predicate :nil :YES :application.managedObjectContext];

if (book !=nil)    NSLog(@"book entity %@",book.title);

Bang ceci dans une classe d'aide statique appelée CoreDataHelper

+ (NSManagedObject*)getEntityFromFetchedResultsController: (NSString*) entityName : (NSPredicate *) predicate : (NSString*) sortKey : (BOOL) sortAscending : (NSManagedObjectContext *) managedObjectContext
{

NSFetchRequest *request = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:entityName inManagedObjectContext:managedObjectContext];
[request setEntity:entity]; 
[request setFetchLimit:1];

// If a predicate was passed, pass it to the query
if(predicate != nil)
{
    [request setPredicate:predicate];
}

// If a sort key was passed, use it for sorting.
if(sortKey != nil)
{
    NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:sortKey ascending:sortAscending];
    NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];
    [request setSortDescriptors:sortDescriptors];
    [sortDescriptors release];
    [sortDescriptor release];
}

NSError *error;

NSMutableArray *mutableFetchResults = [[[managedObjectContext executeFetchRequest:request error:&error] mutableCopy] autorelease];

    if (error !=nil){
NSLog(@"error %@", error);
}
   if ([mutableFetchResults count] >0)
    {
   NSManagedObject *firstObject = [mutableFetchResults objectAtIndex:0];
   return firstObject;
    }else
    {
      return nil;
    }

}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X