如何通过核心数据关系删除所有对象?

sti*_*fin 20 macos cocoa core-data objective-c

假设我有一个自定义的NSManagedObject Department,它有一个表示与员工的多对多关系的属性,即NSSet *employees;.

对于给定的部门,我想删除员工中的所有对象.请问有什么建议/最好的方法吗?

所以,假设我的代码看起来像这样:

Department.h

@interface Department: NSManagedObject {
}
@property (retain) NSString *departmentName;
@property (retain) NSSet *employees;
@end
Run Code Online (Sandbox Code Playgroud)

Department.m

@implementation Department
@dynamic departmentName;
@dynamic employees;
Run Code Online (Sandbox Code Playgroud)

Employee.h

@interface Employee: NSManagedObject {
}
@property (retain) NSString *firstName;
@property (retain) NSString *lastName;
@property (retain) Department *worksIn;
@end
Run Code Online (Sandbox Code Playgroud)

doCoreDataStuff

- (void)doCoreDataStuff:sender {
    //add a department, give it a couple employees, then try to remove those employees
    NSEntityDescription *deptEntity = [NSEntityDescription entityForName:@"Department"
                                                 inManagedObjectContext:self.managedObjectContext];
    Department *dept = [Department alloc] initWithEntity:deptEntity
                          insertIntoManagedObjectContext:self.managedObjectContext];
    NSError *error;

    dept.departmentName = @"Accounting";
    //save more often than normal to see more easily what causes error
    if (![self.managedObjectContext save:&error]) NSLog(@"\nError: %@", [error localizedDescription]);

    NSEntityDescription *empEntity = [NSEntityDescription entityForName:@"Employee"
                                                 inManagedObjectContext:self.managedObjectContext];
    emp.firstName = @"Steve";
    emp.lastName = @"Smith";
    emp.worksIn = dept;

    if (![self.managedObjectContext save:&error]) NSLog(@"\nError: %@", [error localizedDescription]);

    emp = [[Employee alloc] initWithEntity:empEntity
            insertIntoManagedObjectContext:self.managedObjectContext];
    emp.firstName = @"Natasha";
    emp.lastName = @"Johnson";
    emp.worksIn = dept;

    if (![self.managedObjectContext save:&error]) NSLog(@"\nError: %@", [error localizedDescription]);

    //all good so far! now will try to delete all employees for this department
    dept.employees = [NSSet set];
    if (![self.managedObjectContext save:&error]) NSLog(@"\nError: %@", [error localizedDescription]); //"Multiple validation errors occurred."

    //this also produces the same error
    [[dept mutableSetValueForKey:@"employees"] removeAllObjects];
    if (![self.managedObjectContext save:&error]) NSLog(@"\nError: %@", [error localizedDescription]); //"Multiple validation errors occurred."
Run Code Online (Sandbox Code Playgroud)

这种关系employees不是可选的,因此我猜测从部门中删除员工意味着我正在尝试"孤儿"员工,即将员工留在持久模型中而没有相关部门.

因此,我认为我的原始问题应该改为:当孩子与父母有非可选关系时,什么是最好/推荐的方法来删除"父母"的所有"子"对象?

我怀疑答案是"循环并一次删除一个员工对象".

UPDATE

根据答案和Apple文档的链接,我应该能够将删除规则设置为"Cascade",然后代码department.employees = [NSSet set];就可以了.但是,这在我已经相应设置删除规则的非常简单的项目中不起作用.

谢谢

Sco*_*eil 18

将部门的员工关系设置为空集不会删除员工,无论删除规则如何.我相信你误解了删除规则.根据苹果文档:"关系的删除规则指定了在尝试删除源对象时应该发生什么".因此,级联只有在我们删除部门时才会生效.通过将关系设置为空集,我们所做的只是将员工与部门分开,而不是删除它们.如果员工的关系未设置为可选,则在保存时会导致错误.如果要从部门中删除员工,可以按上面列出的方式对其进行迭代,或者将部门关系设置为级联,然后删除部门.


Rem*_*hem 16

如果要删除特定部门的员工元素,则可以像for一样运行for-in循环

for (Employees * theEmployee in department.employees) {
  [self.managedObjectContext deleteObject:[self.managedObjectContext objectWithID:theEmployee.objectID]]; 
}
Run Code Online (Sandbox Code Playgroud)

然后保存您的托管上下文.如果这是你想要的,而不是消除员工和部门之间的关系; 在这种情况下,分配一个空集将起作用.

以上变化:

for (Employee *employeeToDelete in department.employees) {
    [self.managedObjectContext deleteObject:employeeToDelete];
}
Run Code Online (Sandbox Code Playgroud)