如何只读取核心数据中的第一条logging?

我正在使用核心数据,我只想获取我的数据集中的第一条logging,这有可能吗?

您可以使用setFetchLimit:上的setFetchLimit:方法来限制获取的logging数。 所以如果你只想要第一个logging:

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

请注意,调用executeFetchRequest:error:仍然会返回一个NSArray; 您仍然需要将第一个对象从数组中拉出来,然后才能使用它,即使它是大小为1的数组。

另一种效率较低的方法:根据您的商店types,限制提取可能会导致显着的性能提升。 但是,如果没有,或者您不担心性能,并且以后可能会使用更多的数据,则可以提前将第一个对象从数组中提取出来:

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

如果你确定数组里有一个对象,那么你甚至可以通过这样的方式把它放到另一个数组中(例如在UITableViewController中使用):

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

当然这部分取决于你的“第一条logging”是什么意思。 您不仅可以将提取限制设置为1,还可以对提取中的结果进行sorting。

例如,我在我的数据库中有一堆User对象,我想find第一个创build帐户的人。 (假设我已经有了User的模型,包括一个名为accountCreatedDate属性)。

 NSEntityDescription *entity = [NSEntityDescription entityForName:@"User" inManagedObjectContext:managedObjectContext]; NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"accountCreatedDate" ascending:YES]; // ascending YES = start with earliest date NSFetchRequest *request = [[NSFetchRequest alloc] init]; request.entity = entity; request.sortDescriptors = @[ sortDescriptor ]; request.fetchLimit = 1; NSError *error; NSArray *fetchResults = [managedObjectContext executeFetchRequest:request error:&error]; User *result = fetchResults.firstObject; // nil on failure; check value of 'error' 

如果您在限制提取之前没有对结果进行sorting,那么就不会告诉结果将会首先返回。

我使用Objective-C类来添加一个名为firstInManagedObjectContext:NSManagedObject类方法。

源代码

 // 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 

用法

将这些文件添加到您的项目,并确保将其链接到您的目标。 然后,在使用firstInManagedObjectContext:类方法的.m文件中#import "NSManagedObject+Additions.h"

NSManagedObjectContext任何具体(而不是抽象)子类中调用它。 只要传递NSManagedObjectContext *context来从中获取托pipe对象。 该方法从它被调用的类的名称中检测(NSString *)entityName 。 只记得把结果转换成干净的版本(没有警告)。

我正在使用这个pipe理对象类,我知道我只有一个保存的实例。 如果您有多个保存的实例,您可能需要像@Craig McMahon所build议的那样添加一个NSSortDescriptor 。 如果所有的对象都是在同一个设备上创build的,你也可以尝试按objectIDsorting而不是accountCreatedDate 。 但是,我不确定是否订购了对象ID。

想象一下你有一个从NSManagedObjectContextEvent对象。 你可以这样做:

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

在阅读Pragmatic Studio的iOS 4 Blocks教程之后 ,我意识到这个代码可以通过添加另一个函数来改进,甚至更加模块化,调用+ fetch并添加一个NSFetchRequestBlock (将fetchRequest作为参数)和NSFetchRequestFailureBlock作为参数以分别定制提取请求和提取请求错误的处理。 我挑战你解决这个问题! 🙂

只需将fetchLimit属性设置为1,然后使用firstObject方法从结果NSArray选取第一个元素,以避免出现任何index out of bound for empty array错误的index out of bound for empty array

这是代码示例:

 NSFetchRequest *request = [[NSFetchRequest alloc] init]; NSEntityDescription *entity = [NSEntityDescription entityForName:@"ENTITY_NAME" inManagedObjectContext:yourMoc]; NSPedicate *predicate = [NSPredicate predicateWithFormat:@"PREDICATE FORMAT"]; [request setEntity:entity]; [request setPredicate:predicate]; [request setFetchLimit:1]; NSError *error; NSArray *results = [managedObjectContext executeFetchRequest:request error:&error]; NSManagedObject *object = [results firstObject]; if (object) { // there is at least one object matching you predicate } else { // there is no object matching your predicate in the moc } 

这是我的尝试。 注意Book Entity从NSManagedObjectinheritance。

 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); 

把它放在一个叫做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; } }