2

我有一个带有容器和项目实体的核心数据模型。一个容器中可以有零个或多个项目。一个项目必须至少属于一个容器(但它可以在多个容器中。)

关系如下所示:

Container:
  Relationship: items, Destination: Item, Inverse: itemContainers
  Optional, To-Many Relationship
  Delete Rule: Nullify

Item:
  Relationship: itemContainers, Destination: Container, Inverse: items
  Not-Optional, To-Many Relationship
  Delete Rule: Cascade

删除容器时会出现问题。该容器中的 Item 对象已更新,但如果该项目仅存在于一个容器中,则 itemContainers 属性是一个没有对象的集合。保存对象图失败,因为该空集违反了 Item 的 itemContainers 的非可选设置。

当然,使用像“itemContainers.@count == 0”这样的NSPredicate很容易找到带有空itemContainers的Item对象,但似乎应该有一种方法来配置模型以自动执行此操作。

那么有没有更简单/更好的方法?

4

5 回答 5

4

我在上面尝试了Tony Arnold 的回答来解决类似的问题,但是在一次删除多个“容器”时发现了问题(这是在 OS X 10.8.2 上)。[item itemContainers]在保存托管对象上下文之前不会删除容器,因此count保持在 1 以上并且item永远不会被删除。

我想出了以下解决方案-[NSManagedObject isDeleted],在NSManagedObject.

文件NSManagedObject+RJSNondeletedObjects.h

#import <CoreData/CoreData.h>

@interface NSManagedObject (RJSNondeletedObjects)

- (NSSet *)RJS_nondeletedObjectsForToManyKeyPath:(NSString *)keyPath;
- (BOOL)RJS_hasOtherNondeletedObjectsForToManyKeyPath:(NSString *)keyPath;

@end

文件NSManagedObject+RJSNondeletedObjects.m

#import "NSManagedObject+RJSNondeletedObjects.h"

@implementation NSManagedObject (RJSNondeletedObjects)

- (NSSet *)RJS_nondeletedObjectsForToManyKeyPath:(NSString *)keyPath
{
    NSSet * result = nil;

    id allObjectsForKeyPath = [self valueForKeyPath:keyPath];

    if ( ![allObjectsForKeyPath isKindOfClass:[NSSet class]] ) return result;

    result = [(NSSet *)allObjectsForKeyPath objectsPassingTest:^BOOL(id obj, BOOL *stop)
    {
        BOOL testResult = ![obj isDeleted];
        return testResult;
    }];

    return result;
}

- (BOOL)RJS_hasOtherNondeletedObjectsForToManyKeyPath:(NSString *)keyPath
{
    BOOL result = NO;

    // self will be in the set of nondeleted objects, assuming it's not deleted. So we need to adjust the test threshold accordingly.
    NSUInteger threshold = [self isDeleted] ? 0 : 1;
    NSSet * nondeletedObjects = [self RJS_nondeletedObjectsForToManyKeyPath:keyPath];
    result = ( [nondeletedObjects count] > threshold );

    return result;
}

@end

Container班级

...
#import "NSManagedObject+RJSNondeletedObjects.h"
...
- (void)prepareForDeletion
{
    NSSet *childItems = [self items];

    for (Item *item in childItems) {
        if ([item RJS_hasOtherNondeletedObjectsForToManyKeyPath:@"containers"]) {
            continue;
        }

        [managedObjectContext deleteObject:item];
    }
}
于 2012-11-28T02:20:28.680 回答
1

我知道它不像 Core Data 提供的配置选项那么干净,但是我已经部署了一些项目,其中对象在被删除时Container循环通过它的子实体,检查它们是否有 0 (在 'Container.m' 内):ItemitemContainers

- (void)prepareForDeletion
{
    NSSet *childItems = [self items];

    for (Item *item in childItems) {
        if ([[item itemContainers] count] > 1) {
            continue;
        }

        [managedObjectContext deleteObject:item];
    }
}
于 2012-04-20T21:50:48.690 回答
0

在我的应用程序中,我将项目的容器关系设为可选,并通过“智能容器”授予对这些无容器项目的访问权限。

如果你不想这样,我怀疑你只需要处理保存失败,并删除违规对象。

我越来越多地将我对核心数据的处理方式转变为一种防御方式:假设验证将失败,并准备好处理它。当您集成 iCloud 同步时,它变得更加重要。

于 2012-04-20T21:52:52.283 回答
0

我喜欢这样做:

- (void)didChangeValueForKey:(NSString *)inKey withSetMutation:(NSKeyValueSetMutationKind)inMutationKind usingObjects:(NSSet *)inObjects
{
    [super didChangeValueForKey:inKey withSetMutation:inMutationKind usingObjects:inObjects];

    if ([inKey isEqualToString:@"YOURRELATIONSHIP"] && self.YOURRELATIONSHIP.count == 0) {
        [self.managedObjectContext deleteObject:self];
    }
}
于 2013-04-15T14:12:12.527 回答
0

我不认为你可以在你的模型中指定这种行为,但我不是进行那个获取,而是你可以验证itemContainers容器中的计数

 - (void)removeItemObject:(Item *)value
{...
if(![[value itemContainers]count])
  [context deleteObject:value];
...
}
于 2012-04-22T06:31:35.953 回答