Выборка управляемых объектов

Эта статья описывает, как выбрать управляемые объекты и обсуждает некоторые соображения для обеспечения, что выборка эффективна. Это также показывает, как можно использовать NSExpressionDescription объекты получить определенные значения. Для фрагментов кода, которые можно использовать для различных сценариев, посмотрите Базовые Отрывки Данных.

Выборка управляемых объектов

Вы выбираете управляемые объекты путем отправления запроса выборки к контексту управляемого объекта. Вы сначала создаете запрос выборки. Как минимум необходимо указать объект для запроса. Можно получить объект от модели управляемого объекта использование NSEntityDescription метод entityForName:inManagedObjectContext:. Можно также установить предикат (для подробных данных о создании предикатов, см. Руководство по программированию Предиката), дескрипторы вида и другие атрибуты при необходимости. Вы получаете объекты от использования контекста executeFetchRequest:error:, как проиллюстрировано в примере ниже.

  Пример перечисления 1 создания и выполнения запроса выборки

NSManagedObjectContext *moc = [self managedObjectContext];
NSEntityDescription *entityDescription = [NSEntityDescription
    entityForName:@"Employee" inManagedObjectContext:moc];
NSFetchRequest *request = [[NSFetchRequest alloc] init];
[request setEntity:entityDescription];
 
// Set example predicate and sort orderings...
NSNumber *minimumSalary = ...;
NSPredicate *predicate = [NSPredicate predicateWithFormat:
    @"(lastName LIKE[c] 'Worsley') AND (salary > %@)", minimumSalary];
[request setPredicate:predicate];
 
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc]
    initWithKey:@"firstName" ascending:YES];
[request setSortDescriptors:@[sortDescriptor]];
 
NSError *error;
NSArray *array = [moc executeFetchRequest:request error:&error];
if (array == nil)
{
    // Deal with error...
}

Вы не можете выбрать использование предиката на основе переходных свойств (несмотря на то, что можно использовать переходные свойства для просачивания памяти сами). Кроме того, существуют некоторые взаимодействия между выборкой и типом хранилища — для подробных данных, видят Типы Хранилища и Способы поведения. Для суммирования, тем не менее, при выполнении выборки непосредственно Вы не должны обычно добавлять предикаты Объективные на базе С или дескрипторы вида к запросу выборки. Вместо этого необходимо применить их к результатам выборки. При использовании контроллера массива Вы, возможно, должны разделить на подклассы NSArrayController таким образом, у Вас может быть он не, передают дескрипторы вида персистентному хранилищу и вместо этого делают сортировку после того, как были выбраны Ваши данные.

При использовании многократных штабелей персистентности в приложении, или если многократные приложения могли бы получить доступ (и изменить), то же хранилище одновременно, можно выполнить выборки, чтобы гарантировать, что значения данных являются текущими — видят, что Данные Обеспечения Актуальны.

Получение конкретных объектов

Если Ваше приложение использует многократные контексты, и Вы хотите протестировать, был ли объект удален из персистентного хранилища, можно создать запрос выборки с предикатом формы self == %@. Объект, в котором Вы передаете как переменная, может быть или управляемым объектом или управляемым объектом ID, как в следующем примере:

NSFetchRequest *request = [[NSFetchRequest alloc] init];
NSEntityDescription *entity =
    [NSEntityDescription entityForName:@"Employee"
            inManagedObjectContext:managedObjectContext];
[request setEntity:entity];
 
NSPredicate *predicate =
    [NSPredicate predicateWithFormat:@"self == %@", targetObject];
[request setPredicate:predicate];
 
NSError *error;
NSArray *array = [managedObjectContext executeFetchRequest:request error:&error];
if (array != nil) {
    NSUInteger count = [array count]; // May be 0 if the object has been deleted.
    //
}
else {
    // Deal with error.
}

Количество массива, возвращенного из выборки, будет 0 если был удален целевой объект. Если необходимо протестировать на существование нескольких объектов, более эффективно использовать IN оператор, чем он должен выполнить многократные выборки для отдельных объектов, например:

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"self IN %@",
                                            arrayOfManagedObjectIDs];

Выборка определенных значений

Иногда Вы не хотите выбирать фактические управляемые объекты; вместо этого, Вы просто хотите получить — например — самое большое или самое маленькое значение определенного атрибута. В OS X v10.6 и позже и на iOS, можно использовать NSExpressionDescription непосредственно получать значения, удовлетворяющие Ваши критерии.

Вы создаете объект запроса выборки и устанавливаете его объект, как Вы были бы для нормальной выборки, но:

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

  1. Сначала необходимо создать выражения (экземпляры NSExpression) для представления ключевого пути для значения, Вы интересуетесь, и представлять функцию, которую Вы хотите применить (такой как max: или min:):

    NSExpression *keyPathExpression = [NSExpression expressionForKeyPath:@"salary"];
    NSExpression *maxSalaryExpression = [NSExpression expressionForFunction:@"max:"
                                                      arguments:[NSArray arrayWithObject:keyPathExpression]];

    Для полного списка поддерживаемых функций посмотрите expressionForFunction:arguments:.

  2. Вы тогда создаете описание выражения и определяете его имя, выражение и тип результата.

    Имя является ключом, который будет использоваться в словаре для возвращаемого значения. Если Вы хотите получить многократные значения — такой как самое большое и самые маленькие зарплаты в Списке сотрудников — имя каждого описания выражения должно быть уникальным для данного запроса выборки.

    NSExpressionDescription *expressionDescription = [[NSExpressionDescription alloc] init];
    [expressionDescription setName:@"maxSalary"];
    [expressionDescription setExpression:maxSalaryExpression];
    [expressionDescription setExpressionResultType:NSDecimalAttributeType];
  3. Наконец, Вы устанавливаете свойства запроса для выборки просто свойства, представленного выражением:

    [request setPropertiesToFetch:[NSArray arrayWithObject:expressionDescription]];

Можно тогда выполнить запрос выборки так же, как Вы были бы любой другой (использование executeFetchRequest:error:). Возвраты запроса, хотя массив, содержащий словарь, ключи которого и значения соответствуют именам описаний выражения и значений, которые Вы запросили.

Следующий пример иллюстрирует, как можно получить минимальное значение атрибута «creationDate» в объекте под названием «Событие».

NSFetchRequest *request = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:@"Event" inManagedObjectContext:context];
[request setEntity:entity];
 
// Specify that the request should return dictionaries.
[request setResultType:NSDictionaryResultType];
 
// Create an expression for the key path.
NSExpression *keyPathExpression = [NSExpression expressionForKeyPath:@"creationDate"];
 
// Create an expression to represent the minimum value at the key path 'creationDate'
NSExpression *minExpression = [NSExpression expressionForFunction:@"min:" arguments:[NSArray arrayWithObject:keyPathExpression]];
 
// Create an expression description using the minExpression and returning a date.
NSExpressionDescription *expressionDescription = [[NSExpressionDescription alloc] init];
 
// The name is the key that will be used in the dictionary for the return value.
[expressionDescription setName:@"minDate"];
[expressionDescription setExpression:minExpression];
[expressionDescription setExpressionResultType:NSDateAttributeType];
 
// Set the request's properties to fetch just the property represented by the expressions.
[request setPropertiesToFetch:[NSArray arrayWithObject:expressionDescription]];
 
// Execute the fetch.
NSError *error = nil;
NSArray *objects = [managedObjectContext executeFetchRequest:request error:&error];
if (objects == nil) {
    // Handle the error.
}
else {
    if ([objects count] > 0) {
        NSLog(@"Minimum date: %@", [[objects objectAtIndex:0] valueForKey:@"minDate"]);
    }
}

Выборка и наследование объекта

При определении иерархии наследования объекта (см. Наследование Объекта), когда Вы указываете суперобъект как объект для запроса выборки, запрос возвращает все экземпляры соответствия суперобъекта и подобъектов. В некоторых приложениях Вы могли бы указать суперобъект, как являющийся абстрактным (см. Абстрактные Объекты). Для выборки соответствия экземпляров всех конкретных подобъектов абстрактного объекта Вы устанавливаете объект для спецификации выборки, чтобы быть абстрактным объектом. В случае домена, описанного в Абстрактных Объектах, если Вы указываете запрос выборки с Графическим объектом, возвраты выборки, соответствующие экземпляры Круга, TextArea и Строки.