Как выбрать только первую запись в Базовых Данных?

Во время выполнения, когда сообщение отправляется объекту, этот объект переходит к классу, который его создал, и говорит: «Мне было отправлено это сообщение. Запустите код соответствующего метода». Это отличается от большинства языков компиляции, где выполняемый метод определяется во время компиляции.


КАК ЗНАЕТ ОБЪЕКТ, ЧТО ЕГО СОЗДАЛ КЛАСС?

Он использует указатель isa . Каждый объект имеет переменную экземпляра с именем isa. Когда объект создается, класс устанавливает переменную экземпляра isa возвращаемого объекта так, чтобы он указывал на этот класс. Он называется указателем isa, потому что объект является экземпляром этого класса. Хотя вы, вероятно, никогда не будете явно использовать указатель isa, его существование дает Objective-C большую часть его возможностей.


Объект отвечает на сообщение, только если его класс (на который указывает его указатель isa) реализует связанный метод. Поскольку это происходит во время выполнения, XCode не всегда может выяснить во время компиляции (при сборке приложения), будет ли объект отвечать на сообщение. XCode выдаст вам сообщение об ошибке, если посчитает, что вы отправляете сообщение объекту, который не будет отвечать, но если он не уверен, это позволит построить приложение.


Если по какой-то причине (а возможностей много), вы в конечном итоге отправляете сообщение объекту, который не отвечает, ваше приложение выдаст исключение. Таким образом, указатель isa является причиной ошибки во время выполнения . Давайте проверим детали и пример здесь: IOS - Objective-C - исключения и нераспознанные селекторы

39
задан John Calsbeek 11 August 2009 в 14:59
поделиться

3 ответа

Вы можете использовать метод setFetchLimit: в NSFetchRequest, чтобы ограничить количество извлекаемых записей. Итак, если вам нужна только первая запись:

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

Обратите внимание, что вызов executeFetchRequest: error: все равно вернет NSArray; вам все равно нужно вытащить первый объект из массива, прежде чем вы сможете с ним работать, даже если это массив размером 1.

Другой, менее эффективный метод: В зависимости от типа вашего хранилища ограничение выборки может привести к резкое увеличение производительности. Однако, если это не так или вы не слишком беспокоитесь о производительности, и вы можете использовать больше данных позже, вы можете просто вытащить первый объект из массива заранее:

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

Если вы уверены, что в массиве есть объект, вы даже можете поместить его в другой массив (например, для использования в UITableViewController), выполнив следующие действия:

// Again, with some NSArray *results:
NSArray *singleObjectResult = [results subarrayWithRange:NSMakeRange(0, 1)];
75
ответ дан 27 November 2019 в 02:20
поделиться

Конечно, это частично зависит от того, что вы подразумеваете под «первой записью». Вам может потребоваться не только установить предел выборки равным 1, но и отсортировать результаты в выборке.

Например, у меня есть группа объектов 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'

Если вы не отсортируете результаты перед ограничением выборки, невозможно будет сказать, какие результаты будет возвращено "первым".

13
ответ дан 27 November 2019 в 02:20
поделиться

Это моя попытка. N.B. Сущность книги наследуется от 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);

Взломайте это в статическом вспомогательном классе 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;
    }

}    
0
ответ дан 27 November 2019 в 02:20
поделиться
Другие вопросы по тегам:

Похожие вопросы: