在我的Lion应用中,我有这样的数据模型:

Item内的关系子项是有序的。

Xcode 4.1 (build 4B110)为我创建了文件Item.h, Item.h。m, SubItem.h和SubItem.h。

下面是Item.h的内容(自动生成):

#import <Foundation/Foundation.h>

#import <CoreData/CoreData.h>

@class SubItem;

@interface Item : NSManagedObject {
@private
}

@property (nonatomic, retain) NSString * name;
@property (nonatomic, retain) NSOrderedSet *subitems;
@end

@interface Item (CoreDataGeneratedAccessors)

- (void)insertObject:(SubItem *)value inSubitemsAtIndex:(NSUInteger)idx;
- (void)removeObjectFromSubitemsAtIndex:(NSUInteger)idx;
- (void)insertSubitems:(NSArray *)value atIndexes:(NSIndexSet *)indexes;
- (void)removeSubitemsAtIndexes:(NSIndexSet *)indexes;
- (void)replaceObjectInSubitemsAtIndex:(NSUInteger)idx withObject:(SubItem *)value;
- (void)replaceSubitemsAtIndexes:(NSIndexSet *)indexes withSubitems:(NSArray *)values;
- (void)addSubitemsObject:(SubItem *)value;
- (void)removeSubitemsObject:(SubItem *)value;
- (void)addSubitems:(NSOrderedSet *)values;
- (void)removeSubitems:(NSOrderedSet *)values;

@end

下面是Item.m的内容(自动生成):

#import "Item.h"
#import "SubItem.h"

@implementation Item

@dynamic name;
@dynamic subitems;

@end

如您所见,Item类提供了一个名为addSubitemsObject:的方法。不幸的是,当你试图以这种方式使用它时:

Item *item = [NSEntityDescription insertNewObjectForEntityForName:@"Item" inManagedObjectContext:self.managedObjectContext];
item.name = @"FirstItem";

SubItem *subItem = [NSEntityDescription insertNewObjectForEntityForName:@"SubItem" inManagedObjectContext:self.managedObjectContext];

[item addSubitemsObject:subItem];

出现以下错误:

2011-09-12 10:28:45.236 Test[2002:707] *** -[NSSet intersectsSet:]: set argument is not an NSSet

你能帮我吗?

更新:

在我的错误报告刚刚过去1787天之后,今天(2016年8月1日),苹果公司给我写了这样的话:“请用最新的iOS 10测试版验证这个问题,并在bugreport.apple.com上更新你的错误报告。”让我们希望这是正确的时间:)


当前回答

如果你正在使用mogenerator,那么代替

[parentObject add<Child>sObject:childObject];

简单的使用方法:

[[parent object <child>sSet] addObject:childObject];

其他回答

我刚刚遇到了这个问题,并使用一个比这里介绍的其他实现简单得多的实现解决了这个问题。我只是使用NSManagedObject上可用的方法来处理不使用子类时的关系。

一个插入实体到NSOrderedSet关系的示例实现如下所示:

- (void)addAddress:(Address *)address
{
    if ([self.addresses containsObject:address]) {
        return;
    }
    // Use NSManagedObject's methods for inserting an object
    [[self mutableOrderedSetValueForKey:@"addresses"] addObject:address];
}

这是完美的工作,并且是我在移动到NSManagedObject子类之前使用的。

就我个人而言,我刚刚用@Stephan在另一个解决方案中概述的方法直接调用替换了对CoreData生成方法的调用:

NSMutableOrderedSet* tempSet = [self mutableOrderedSetValueForKey:@"subitems"];
      [tempSet addObject:value];
[tempSet addObject:value];

这消除了对类别的需求,当错误修复后,这些类别可能与苹果的解决方案和生成的代码发生冲突。

这有一个额外的好处,就是它是官方的方式!

我刚刚在Swift (Xcode 6.1.1)中遇到了问题。

答案是不要在NSManagedObject子类中编写任何方法或其他东西。我认为这是一个编译器错误。非常奇怪的虫子。

希望能有所帮助。

罗伯特,

我同意你的答案可以解决这个问题,但是请记住,已经有一种自动创建的方法可以将一整套值添加到关系中。苹果的文档(见“多对关系”部分或“自定义多对关系访问器方法”部分)是这样实现的:

- (void)addEmployees:(NSSet *)value
{
[self willChangeValueForKey:@"employees"
      withSetMutation:NSKeyValueUnionSetMutation
      usingObjects:value];
[[self primitiveEmployees] unionSet:value];
[self didChangeValueForKey:@"employees"
      withSetMutation:NSKeyValueUnionSetMutation
      usingObjects:value];
}

- (void)removeEmployees:(NSSet *)value
{
[self willChangeValueForKey:@"employees"
      withSetMutation:NSKeyValueMinusSetMutation
      usingObjects:value];
[[self primitiveEmployees] minusSet:value];
[self didChangeValueForKey:@"employees"
      withSetMutation:NSKeyValueMinusSetMutation
      usingObjects:value];
}

您可以很容易地在核心数据之外编译您的关系集,然后使用此方法一次性添加它们。它可能没有你建议的方法那么难看;)

似乎如果你通过设置父节点和子节点而不是相反的方式来连接父节点和子节点,它就不会崩溃。

所以如果你这样做:

[child setParent:parent]

而不是

[parent setChildObects:child]

它应该可以工作,至少在iOS 7上可以工作,而且关系没有任何问题。