Cocoa Core Data: установка значений свойств сущности по умолчанию?

Я знаю, что могу установить значения по умолчанию либо в модели данных, либо в методе -awakeFromInsert класса сущности. Например, чтобы сделать свойство «дата» по умолчанию текущей датой:

- (void) awakeFromInsert
{
NSDate *now = [NSDate date];
self.date = now;
}

Как я могу сделать свойство «idNumber» по умолчанию на единицу больше, чем idNumber предыдущего объекта?

Спасибо, Оли

EDIT: Соответствующий код для моей попытки (сейчас исправлено)

- (void) awakeFromInsert
{
self.idNumber = [NSNumber numberWithInt:[self maxIdNumber] + 1];
}

-(int)maxIdNumber{
NSManagedObjectContext *moc = [self managedObjectContext];
NSEntityDescription *entityDescription = [NSEntityDescription entityForName:@"Flight" inManagedObjectContext:moc];
NSFetchRequest *request = [[[NSFetchRequest alloc] init] autorelease];
[request setEntity:entityDescription];

// Set example predicate and sort orderings...
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"idNumber > %@", [NSNumber numberWithInt:0]];
[request setPredicate:predicate];

[request setFetchLimit:1];

NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"idNumber" ascending:NO];
[request setSortDescriptors:[NSArray arrayWithObject:sortDescriptor]];
[sortDescriptor release];

NSError *error;
NSArray *array = [moc executeFetchRequest:request error:&error];
if (array == nil | array.count == 0)
{
    return 0;
} 
return [[[array objectAtIndex:0] valueForKey:@"idNumber"] intValue];
}

При вызове метода maxIdNumber новый объект добавляется в таблицу дважды!? (но с правильным idNumber). Две записи в таблице связаны — редактирование/удаление одной также редактирует/удаляет другую. По этой причине я считаю, что это как-то связано с контекстом управляемого объекта. Как бы то ни было, результат (две копии) один и тот же, независимо от того, сколько раз вызывается метод maxIdNumber в awakFromNib; даже если для self.idNumber просто установлено значение [NSNumber numberWithInt:5], а метод maxIdNumber просто вызывается для одноразовой переменной.

Есть подсказки??


person Community    schedule 16.09.2010    source источник
comment
Кстати, Apple не рекомендует использовать собственные значения ID в сущностях. Вы можете использовать метод objectID NSManagedObject для получения объекта NSManagedObjectID, и он будет уникальным для любого объекта.   -  person beefon    schedule 16.09.2010
comment
К сожалению, этот идентификатор меняется с временного на постоянный, когда он сохраняется в магазине. Понятно, что большинство разработчиков просто используют свою собственную систему идентификации для простоты, и она отлично работает.   -  person Joshua Nozzi    schedule 17.09.2010
comment
Спасибо, поле idNumber не предназначено для различения объектов, это свойство сущности, которую должен предоставить пользователь (они могут выбрать два объекта с одинаковым idNumber, есть выбор!!). Он будет отображаться в таблице вместе с другими свойствами объекта.   -  person    schedule 17.09.2010


Ответы (3)


РЕШЕНО!

Хорошо, проблема двойной записи возникает, когда запрос на выборку выполняется из метода awakeFromInsert. Цитата из документов< /а>:

Обычно вам не рекомендуется выполнять выборку в рамках реализации awakeFromInsert. Хотя это разрешено, выполнение запроса на выборку может вызвать отправку внутренних уведомлений Core Data, которые могут иметь нежелательные побочные эффекты. Например, в Mac OS X экземпляр NSArrayController может дважды вставить новый объект в свой массив содержимого.

Способ обойти это — использовать метод perfromSelector:withObject:afterDelay, как описано здесь (мне разрешено публиковать только одну гиперссылку :( ):http://www.cocoabuilder.com/archive/cocoa/232606-auto-incrementing-integer-attribute-in-awakefrominsert.html.

Мой рабочий код теперь выглядит следующим образом: (обратите внимание, я поместил большую часть кода выборки, использованного выше, в категорию, чтобы немного привести его в порядок, это позволяет мне использовать метод fetchObjectsForEntityName:withPredicate:withFetchLimit:withSortDescriptors: )

- (void) awakeFromInsert
{
[self performSelector:@selector(setIdNumber) withObject:nil afterDelay:0];
self.date = [NSDate date];
}


-(void)setIdNumber
{
int num  = 0;

NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"idNumber" ascending:NO];
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"idNumber > %@", [NSNumber numberWithInt:0]];

NSArray *array = [[self managedObjectContext] fetchObjectsForEntityName:@"Flight" 
                                                          withPredicate:predicate 
                                                         withFetchLimit:0
                                                    withSortDescriptors:[NSArray arrayWithObject:sortDescriptor]];
[sortDescriptor release];   

if (array != nil & array.count != 0)
{
    num = [[[array objectAtIndex:0] valueForKey:@"idNumber"] intValue]; 
} 

num ++;

[self setIdNumber:[NSNumber numberWithInt:num]];
}

Дайте мне знать, что вы думаете!

person Community    schedule 17.09.2010
comment
Если это ответ, поставьте галочку, чтобы система отобразила его как ответ. - person TechZen; 17.09.2010
comment
Я не могу, я должен ждать до завтра, чтобы принять свой собственный ответ :( !! - person ; 17.09.2010

Один подход. Создайте запрос на выборку всех экземпляров вашего объекта с ограничением 1, отсортированных по idNumber, чтобы получить наибольшее число.

Другой подход. Сохраняйте самый высокий idNumber в метаданных вашего магазина и продолжайте увеличивать его.

Аргументов как за, так и против предостаточно. В конечном счете, это два наиболее распространенных, и выбор за вами.

person Joshua Nozzi    schedule 16.09.2010
comment
Спасибо за ваш ответ. Итак, мне удалось создать запрос на выборку, который возвращает самый высокий idNumber, отлично! Однако всякий раз, когда я использую этот код для установки свойства idNumber, объект дважды добавляется в таблицу!?!?! (Хотя удаление любого из двух экземпляров с помощью кнопки удаления удаляет оба). Любые идеи? - person ; 17.09.2010
comment
Ну вот, я поместил это в исходный пост, чтобы сделать его более разборчивым. - person ; 17.09.2010
comment
Похоже, вы не показываете, как используется -maxIDNumber. - person Joshua Nozzi; 17.09.2010
comment
Ах, извините. Хорошо, вся соответствующая информация теперь должна быть в исходном сообщении. Кроме того, этот код для запроса на выборку довольно многословен, я планировал переместить его в категорию, чтобы предоставить более аккуратный метод наподобие строк fetchObjectsForEntityName: withPredicate: withFetchLimit: withSortDescriptors:. Плохая идея, хорошая идея? - person ; 17.09.2010
comment
Почему ваш возвращаемый тип NSNumber, когда вы возвращаете int? Я не уловил этого изначально. - person Joshua Nozzi; 17.09.2010
comment
Это не так, извините, я изменил метод, чтобы вернуть int. Сейчас поправил выше. Тем не менее, это не объясняет двойные записи... - person ; 17.09.2010

Более простой способ сделать это — переопределить метод newObject NSArrayController:

- (id) newObject
{
    id result=[super newObject];
    [result setValue: [NSDate date] forKey: @"date"];
    return result;
}
person Ramy Al Zuhouri    schedule 28.07.2012