Почему CoreData не предоставляет класс с именем NSDeleteRequest, как NSFetchRequest - PullRequest
0 голосов
/ 07 августа 2011

Мне было интересно, почему CoreData Framework iPhone не предоставляет возможность удалять объекты из базы данных в группе, используя NSPredicate. Они предоставили способ извлечения данных с помощью NSFetchRequest, но я не нашел ни одного метода или класса для удаления объектов в группе с помощью NSPredicate. Например, я хочу удалить те объекты из таблицы клиентов, где баланс клиента равен нулю. Я могу сделать это с помощью цикла for в основных данных, но я хотел знать, почему Apple не предоставила способ удаления объектов таким способом?

1 Ответ

1 голос
/ 07 августа 2011

Вы должны иметь возможность удалять объекты из базы данных, используя метод NSManagedObjectContext deleteObject:. Точно так же, если вы создали файлы .h и .m из вашей базовой модели данных, он должен был создать методы для объекта, чтобы удалить объекты отношения один-ко-многим из себя (что-то похожее на -(void)removeCustomersObject:(Customer *)value или -(void)removeCustomers:(NSSet *)value.

Используя эту информацию, вы сможете установить параметр, который проверяет, равен ли баланс нулю, и удаляет объекты одним из этих методов. Иногда можно использовать запрос на выборку, чтобы найти всех клиентов с нулевым балансом (используя NSPredicate), и удалить полученные результаты из вашей базы данных. Я надеюсь, что это помогает и дает вам представление, куда идти. Я был бы более подробным, но трудно дать слишком много советов без дополнительной информации. В любом случае, это должно послужить хорошей отправной точкой для решения вашей проблемы.

РЕДАКТИРОВАТЬ: Существует два способа удаления нескольких объектов из базовых данных. Самое простое предполагает, что у вас есть две сущности. Одним из них является родитель, который я бы назвал MyDatabase, который удерживает всех детей в отношениях «один ко многим». Это будут ваши объекты Customer или Person. То, что вы называете, не так уж важно, но это объекты с балансом. Для этого примера я просто назову класс Customer.

Если вы сгенерируете код для сущностей (перейдя в файл xcdatamodeld, выбрав сущности, затем перейдите в Editor-> Create NSManagedObject Subclass), вы увидите нечто подобное для родительской сущности.

@class Customer;
@interface MyDatabase : NSManagedObject {
}
@property (nonatomic, retain) NSSet *customers;

и в вашем .m файле

@implementation MyDatabase
@dynamic customers

- (void)addCustomersObject:(Customer *)value {    
    NSSet *changedObjects = [[NSSet alloc] initWithObjects:&value count:1];
    [self willChangeValueForKey:@"customers" withSetMutation:NSKeyValueUnionSetMutation usingObjects:changedObjects];
    [[self primitiveValueForKey:@"customers"] addObject:value];
    [self didChangeValueForKey:@"customers" withSetMutation:NSKeyValueUnionSetMutation usingObjects:changedObjects];
    [changedObjects release];
}

- (void)removeCustomersObject:(Customer *)value {
    NSSet *changedObjects = [[NSSet alloc] initWithObjects:&value count:1];
    [self willChangeValueForKey:@"givenSurveys" withSetMutation:NSKeyValueMinusSetMutation usingObjects:changedObjects];
    [[self primitiveValueForKey:@"customers"] removeObject:value];
    [self didChangeValueForKey:@"customers" withSetMutation:NSKeyValueMinusSetMutation usingObjects:changedObjects];
    [changedObjects release];
}

- (void)addCustomers:(NSSet *)value {    
    [self willChangeValueForKey:@"customers" withSetMutation:NSKeyValueUnionSetMutation usingObjects:value];
    [[self primitiveValueForKey:@"customers"] unionSet:value];
    [self didChangeValueForKey:@"customers" withSetMutation:NSKeyValueUnionSetMutation usingObjects:value];
}

- (void)removeCustomers:(NSSet *)value {
    [self willChangeValueForKey:@"customers" withSetMutation:NSKeyValueMinusSetMutation usingObjects:value];
    [[self primitiveValueForKey:@"customers"] minusSet:value];
    [self didChangeValueForKey:@"customers" withSetMutation:NSKeyValueMinusSetMutation usingObjects:value];
}

Опять же, они создаются для вас при создании файла, хотя, если по какой-то причине это не так, вы, возможно, неправильно настроили отношения.

Чтобы удалить файлы, вам нужно получить контекст, используя предикат. Возвращаемым запросом является NSArray с объектами, которые соответствуют критериям (баланс 0). Для этого примера мы просто назовем этот массив objectsToRemove. На данный момент мы готовы рассмотреть оба возможных решения.

1) В этом случае у вас нет карты дочерних / родительских сущностей для ваших Базовых данных, а есть только одна сущность. В этом случае вы будете использовать свой запрос на выборку, как описано выше. Тогда вы будете называть что-то вроде следующего

for (id myObject in objectsToDelete) {
    [self.managedObjectContext deleteObject:myObject];
}
// commit the changes;
NSError *error = nil;
if (![self.managedObjectContext save:&error]) {
    // handle the error;
}

При этом удаляются все объекты, а затем сохраняется ваш контекст.

2) Если у вас есть родительская / дочерняя карта базовых данных, это станет проще. В этом случае вы просто позвоните по следующему во время запроса на получение

[myDatabase removeCustomers:[NSSet setWithArray:objectsToDelete]];
// commit the changes;
NSError *error = nil;
if (![self.managedObjectContext save:&error]) {
    // handle the error;
}

Второй подход удаляет все объекты одновременно, но требует наличия сущности, которая содержит Customer объекты. На мой взгляд, это более хороший подход, хотя и не обязательный, особенно если вам не нужно разделять Customer объекты на разные группы. В этом учебнике Core Data представлен обзор классического проекта Department and Employees, который является очень простым, но наглядным примером того, как родительские / дочерние иерархии используются в Core Data.

...