在我的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上更新你的错误报告。”让我们希望这是正确的时间:)


当前回答

苹果文档To Many Relations说:你应该访问代理可变集或有序集使用

NSMutableOrderedSet * set = [managedObject mutableOrderedSetValueForKey:@"toManyRelation"];

修改此集合将添加或删除与托管对象的关系。使用[]或访问器访问可变有序集。符号是错误的,会失败。

其他回答

我通过谷歌错误信息找到了这个问题,只是想指出我以一种稍微不同的方式(不是使用有序集)遇到了这个错误。这并不完全是对给定问题的答案,但我把它贴在这里,以防它对其他在搜索时偶然发现这个问题的人有帮助。

我正在添加一个新的模型版本,并向现有模型添加了一些关系,并在头文件中自己定义了add*Object方法。当我尝试调用它们时,我得到了上面的错误。

在检查了我的模型之后,我意识到我愚蠢地忘记了勾选“to - many Relationship”复选框。

所以如果你遇到这种情况,你没有使用有序集,仔细检查你的模型。

我也遇到过同样的问题,但只是在我尝试了一些与我一直在做的不同的事情时。我无法看到subItem的代码,但我将假设它具有到item的反向链接。让我们称之为崇敬链接,“parentItem”,那么最简单的解决方案是:

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

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

//[item addSubitemsObject:subItem];
subItem.parentItem = item;

结果是它使用了苹果自己的代码,而且简单干净。此外,集合被自动添加到,并且所有的观察者都被更新。没有问题。

相反,我建议使用NSObject中的访问器来访问关系的NSMutableOrderedSet。

- (void)addSubitemsObject:(SubItem *)value {
      NSMutableOrderedSet* tempSet = [self mutableOrderedSetValueForKey:@"subitems"];
      [tempSet addObject:value];
 }

例如,iOS v5.0的核心数据发布说明参考了这一点。

在一个简短的测试中,它在我的应用程序中工作。

我在用XCode 7将一个项目从Objective-C迁移到Swift 2时遇到了这个问题。这个项目过去是有效的,而且有一个很好的理由:我使用MOGenerator,它有替换方法来修复这个错误。但并不是所有的方法都需要替换。

这里有一个完整的解决方案和一个示例类,尽可能地依赖默认访问器。

假设我们有一个包含有序项的List

首先,如果你有一对多的关系,最简单的方法就是:

item.list = list

而不是

list.addItemsObject(item)

现在,如果这不是一个选择,以下是你可以做的:

// Extension created from your DataModel by selecting it and
// clicking on "Editor > Create NSManagedObject subclass…"

extension List {
  @NSManaged var items: NSOrderedSet?
}

class List

  // Those two methods work out of the box for free, relying on
  // Core Data's KVC accessors, you just have to declare them
  // See release note 17583057 https://developer.apple.com/library/prerelease/tvos/releasenotes/DeveloperTools/RN-Xcode/Chapters/xc7_release_notes.html
  @NSManaged func removeItemsObject(item: Item)
  @NSManaged func removeItems(items: NSOrderedSet)

  // The following two methods usually work too, but not for NSOrderedSet
  // @NSManaged func addItemsObject(item: Item)
  // @NSManaged func addItems(items: NSOrderedSet)

  // So we'll replace them with theses

  // A mutable computed property
  var itemsSet: NSMutableOrderedSet {
    willAccessValueForKey("items")
    let result = mutableOrderedSetValueForKey("items")
    didAccessValueForKey("items")
    return result
  }

  func addItemsObject(value: Item) {
    itemsSet.addObject(value)
  }

  func addItems(value: NSOrderedSet) {
    itemsSet.unionOrderedSet(value)
  }
end

当然,如果你使用的是Objective-C,你可以做完全相同的事情,因为这是我最初得到的想法:)

罗伯特,

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

- (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];
}

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