Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/cocoa/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Cocoa 在数据集生成的访问器中引发异常_Cocoa_Core Data_Xcode4 - Fatal编程技术网

Cocoa 在数据集生成的访问器中引发异常

Cocoa 在数据集生成的访问器中引发异常,cocoa,core-data,xcode4,Cocoa,Core Data,Xcode4,在我的Lion应用程序中,我有以下数据模型: 项中的关系子项已排序 Xcode 4.1 build 4B110为我创建了文件Item.h、Item.m、SubItem.h和SubItem.h 以下是项的自动生成内容。h: 如您所见,类项提供了一个名为addSubitemsObject的方法:。不幸的是,当试图以这种方式使用它时: Item *item = [NSEntityDescription insertNewObjectForEntityForName:@"Item" inManagedO

在我的Lion应用程序中,我有以下数据模型:

项中的关系子项已排序

Xcode 4.1 build 4B110为我创建了文件Item.h、Item.m、SubItem.h和SubItem.h

以下是项的自动生成内容。h:

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

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

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

[item addSubitemsObject:subItem];
- (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];
}
出现以下错误:

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

更新:


在我的bug报告发布仅1787天后,今天2016年8月1日,苹果给我写了这样一封信:请用最新的iOS 10 beta版本验证这个问题,并在bugreport.Apple.com上用您的结果更新您的bug报告。。希望这是正确的时机:

我用您的数据模型和我自己的一个不同名称复制了您的设置。我在两种情况下都犯了同样的错误


看起来像是苹果自动生成代码中的一个bug

我同意这里可能有一个bug。我修改了addobjectsetter的实现,以便正确地附加到NSMutableOrderedSet

- (void)addSubitemsObject:(SubItem *)value {
    NSMutableOrderedSet* tempSet = [NSMutableOrderedSet orderedSetWithOrderedSet:self.subitems];
    [tempSet addObject:value];
    self.subitems = tempSet;
}
- (void)addSubitemsObject:(SubItem *)value {
     NSMutableOrderedSet* tempSet = [NSMutableOrderedSet orderedSetWithOrderedSet:self.subitems];
     [tempSet addObject:value];
     self.subitems = tempSet;
}
将集合重新分配给self.subitems将确保发送will/DidChangeValue通知

我同意这里可能有个bug。我修改了addobject>setter的实现,以便正确地附加到NSMutableOrderedSet

- (void)addSubitemsObject:(SubItem *)value {
    NSMutableOrderedSet* tempSet = [NSMutableOrderedSet orderedSetWithOrderedSet:self.subitems];
    [tempSet addObject:value];
    self.subitems = tempSet;
}
- (void)addSubitemsObject:(SubItem *)value {
     NSMutableOrderedSet* tempSet = [NSMutableOrderedSet orderedSetWithOrderedSet:self.subitems];
     [tempSet addObject:value];
     self.subitems = tempSet;
}
将集合重新分配给self.subitems将确保发送will/DidChangeValue notifications>


Leelll,您确定在自定义设置NSMutableOrderedSet之后,存储在该集合中的NSMutableOrderedSet值会被CoreData正确保存到数据库中吗?我没有检查这一点,但CoreData似乎对NSOrderedSet一无所知,并希望NSSet作为许多关系容器。

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

- (void)addSubitemsObject:(SubItem *)value {
      NSMutableOrderedSet* tempSet = [self mutableOrderedSetValueForKey:@"subitems"];
      [tempSet addObject:value];
 }
@property (nonatomic, retain) NSMutableArray* tempItems;
 ....
@synthesize tempItems = _tempItems;
 ....

- (void) addItemsObject:(KDItem *)value 
{
    if (!_tempItems) {
        self.tempItems = [NSMutableArray arrayWithCapacity:500];
    }
    [_tempItems addObject:value];
}

// Call this when you have added all the relationships
- (void) commitRelationships 
{
    if (_tempItems) {
        self.items = [NSOrderedSet orderedSetWithArray:self.tempItems];
        self.tempItems = nil;
    }
}
e、 g.本文件指的是本文件


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

我有一个名为signals的项目,而不是子项目。tempset解决方案在我的测试中有效。此外,我对removeSignals:method有一个问题。这种覆盖似乎有效:

- (void)removeSignals:(NSOrderedSet *)values {
    NSMutableOrderedSet* tempset = [NSMutableOrderedSet orderedSetWithOrderedSet:self.signals];
    for (Signal* aSignal in values) {
        [tempset removeObject:aSignal];
    }
    self.signals = tempset;
}
如果有更好的方法,请告诉我。我的值输入从不超过10-20项,因此性能不太重要-尽管如此,请指出任何相关内容

谢谢


Damien收到了相同的错误,@LeeIII解决方案对我有效,谢谢!。我建议稍微修改一下:

使用objective-c类别存储新方法,这样,如果再次生成项目,我们就不会丢失方法 检查我们是否已经有可变集合 项目+类别的内容。m:


我决定通过实施所有必需的方法来改进解决方案:

static NSString *const kItemsKey = @"<#property#>";

- (void)insertObject:(<#Type#> *)value in<#Property#>AtIndex:(NSUInteger)idx {
    NSIndexSet* indexes = [NSIndexSet indexSetWithIndex:idx];
    [self willChange:NSKeyValueChangeInsertion valuesAtIndexes:indexes forKey:kItemsKey];
    NSMutableOrderedSet *tmpOrderedSet = [NSMutableOrderedSet orderedSetWithOrderedSet:[self mutableOrderedSetValueForKey:kItemsKey]];
    [tmpOrderedSet insertObject:value atIndex:idx];
    [self setPrimitiveValue:tmpOrderedSet forKey:kItemsKey];
    [self didChange:NSKeyValueChangeInsertion valuesAtIndexes:indexes forKey:kItemsKey];
}

- (void)removeObjectFrom<#Property#>AtIndex:(NSUInteger)idx {
    NSIndexSet* indexes = [NSIndexSet indexSetWithIndex:idx];
    [self willChange:NSKeyValueChangeRemoval valuesAtIndexes:indexes forKey:kItemsKey];
    NSMutableOrderedSet *tmpOrderedSet = [NSMutableOrderedSet orderedSetWithOrderedSet:[self mutableOrderedSetValueForKey:kItemsKey]];
    [tmpOrderedSet removeObjectAtIndex:idx];
    [self setPrimitiveValue:tmpOrderedSet forKey:kItemsKey];
    [self didChange:NSKeyValueChangeRemoval valuesAtIndexes:indexes forKey:kItemsKey];
}

- (void)insert<#Property#>:(NSArray *)values atIndexes:(NSIndexSet *)indexes {
    [self willChange:NSKeyValueChangeInsertion valuesAtIndexes:indexes forKey:kItemsKey];
    NSMutableOrderedSet *tmpOrderedSet = [NSMutableOrderedSet orderedSetWithOrderedSet:[self mutableOrderedSetValueForKey:kItemsKey]];
    [tmpOrderedSet insertObjects:values atIndexes:indexes];
    [self setPrimitiveValue:tmpOrderedSet forKey:kItemsKey];
    [self didChange:NSKeyValueChangeInsertion valuesAtIndexes:indexes forKey:kItemsKey];
}

- (void)remove<#Property#>AtIndexes:(NSIndexSet *)indexes {
    [self willChange:NSKeyValueChangeRemoval valuesAtIndexes:indexes forKey:kItemsKey];
    NSMutableOrderedSet *tmpOrderedSet = [NSMutableOrderedSet orderedSetWithOrderedSet:[self mutableOrderedSetValueForKey:kItemsKey]];
    [tmpOrderedSet removeObjectsAtIndexes:indexes];
    [self setPrimitiveValue:tmpOrderedSet forKey:kItemsKey];
    [self didChange:NSKeyValueChangeRemoval valuesAtIndexes:indexes forKey:kItemsKey];
}

- (void)replaceObjectIn<#Property#>AtIndex:(NSUInteger)idx withObject:(<#Type#> *)value {
    NSIndexSet* indexes = [NSIndexSet indexSetWithIndex:idx];
    [self willChange:NSKeyValueChangeReplacement valuesAtIndexes:indexes forKey:kItemsKey];
    NSMutableOrderedSet *tmpOrderedSet = [NSMutableOrderedSet orderedSetWithOrderedSet:[self mutableOrderedSetValueForKey:kItemsKey]];
    [tmpOrderedSet replaceObjectAtIndex:idx withObject:value];
    [self setPrimitiveValue:tmpOrderedSet forKey:kItemsKey];
    [self didChange:NSKeyValueChangeReplacement valuesAtIndexes:indexes forKey:kItemsKey];
}

- (void)replace<#Property#>AtIndexes:(NSIndexSet *)indexes with<#Property#>:(NSArray *)values {
    [self willChange:NSKeyValueChangeReplacement valuesAtIndexes:indexes forKey:kItemsKey];
    NSMutableOrderedSet *tmpOrderedSet = [NSMutableOrderedSet orderedSetWithOrderedSet:[self mutableOrderedSetValueForKey:kItemsKey]];
    [tmpOrderedSet replaceObjectsAtIndexes:indexes withObjects:values];
    [self setPrimitiveValue:tmpOrderedSet forKey:kItemsKey];
    [self didChange:NSKeyValueChangeReplacement valuesAtIndexes:indexes forKey:kItemsKey];
}

- (void)add<#Property#>Object:(<#Type#> *)value {
    NSMutableOrderedSet *tmpOrderedSet = [NSMutableOrderedSet orderedSetWithOrderedSet:[self mutableOrderedSetValueForKey:kItemsKey]];
    NSUInteger idx = [tmpOrderedSet count];
    NSIndexSet* indexes = [NSIndexSet indexSetWithIndex:idx];
    [self willChange:NSKeyValueChangeInsertion valuesAtIndexes:indexes forKey:kItemsKey];
    [tmpOrderedSet addObject:value];
    [self setPrimitiveValue:tmpOrderedSet forKey:kItemsKey];
    [self didChange:NSKeyValueChangeInsertion valuesAtIndexes:indexes forKey:kItemsKey];
}

- (void)remove<#Property#>Object:(<#Type#> *)value {
    NSMutableOrderedSet *tmpOrderedSet = [NSMutableOrderedSet orderedSetWithOrderedSet:[self mutableOrderedSetValueForKey:kItemsKey]];
    NSUInteger idx = [tmpOrderedSet indexOfObject:value];
    if (idx != NSNotFound) {
        NSIndexSet* indexes = [NSIndexSet indexSetWithIndex:idx];
        [self willChange:NSKeyValueChangeRemoval valuesAtIndexes:indexes forKey:kItemsKey];
        [tmpOrderedSet removeObject:value];
        [self setPrimitiveValue:tmpOrderedSet forKey:kItemsKey];
        [self didChange:NSKeyValueChangeRemoval valuesAtIndexes:indexes forKey:kItemsKey];
    }
}

- (void)add<#Property#>:(NSOrderedSet *)values {
    NSMutableOrderedSet *tmpOrderedSet = [NSMutableOrderedSet orderedSetWithOrderedSet:[self mutableOrderedSetValueForKey:kItemsKey]];
    NSMutableIndexSet *indexes = [NSMutableIndexSet indexSet];
    NSUInteger valuesCount = [values count];
    NSUInteger objectsCount = [tmpOrderedSet count];
    for (NSUInteger i = 0; i < valuesCount; ++i) {
        [indexes addIndex:(objectsCount + i)];
    }
    if (valuesCount > 0) {
        [self willChange:NSKeyValueChangeInsertion valuesAtIndexes:indexes forKey:kItemsKey];
        [tmpOrderedSet addObjectsFromArray:[values array]];
        [self setPrimitiveValue:tmpOrderedSet forKey:kItemsKey];
        [self didChange:NSKeyValueChangeInsertion valuesAtIndexes:indexes forKey:kItemsKey];
    }
}

- (void)remove<#Property#>:(NSOrderedSet *)values {
    NSMutableOrderedSet *tmpOrderedSet = [NSMutableOrderedSet orderedSetWithOrderedSet:[self mutableOrderedSetValueForKey:kItemsKey]];
    NSMutableIndexSet *indexes = [NSMutableIndexSet indexSet];
    for (id value in values) {
        NSUInteger idx = [tmpOrderedSet indexOfObject:value];
        if (idx != NSNotFound) {
            [indexes addIndex:idx];
        }
    }
    if ([indexes count] > 0) {
        [self willChange:NSKeyValueChangeRemoval valuesAtIndexes:indexes forKey:kItemsKey];
        [tmpOrderedSet removeObjectsAtIndexes:indexes];
        [self setPrimitiveValue:tmpOrderedSet forKey:kItemsKey];
        [self didChange:NSKeyValueChangeRemoval valuesAtIndexes:indexes forKey:kItemsKey];
    }
}

我发现使用LeeIII的方法是有效的,但在分析时发现速度非常慢。解析1000个项目花费了15秒。注释代码以添加关系将15秒变为2秒

我的解决方法更快,但更难看,包括创建一个临时可变数组,然后在所有解析完成后复制到有序集。如果您要添加许多关系,这只是一个性能胜利

- (void)addSubitemsObject:(SubItem *)value {
      NSMutableOrderedSet* tempSet = [self mutableOrderedSetValueForKey:@"subitems"];
      [tempSet addObject:value];
 }
@property (nonatomic, retain) NSMutableArray* tempItems;
 ....
@synthesize tempItems = _tempItems;
 ....

- (void) addItemsObject:(KDItem *)value 
{
    if (!_tempItems) {
        self.tempItems = [NSMutableArray arrayWithCapacity:500];
    }
    [_tempItems addObject:value];
}

// Call this when you have added all the relationships
- (void) commitRelationships 
{
    if (_tempItems) {
        self.items = [NSOrderedSet orderedSetWithArray:self.tempItems];
        self.tempItems = nil;
    }
}
我希望这能帮助别人

罗伯特

我同意你的答案对这一点有用,但请记住,有一种自动创建的方法可以向关系中添加一整套值。Apple在“多对多关系”部分或“自定义多对多关系访问器方法”部分下的文档以以下方式实现它们:

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

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

[item addSubitemsObject:subItem];
- (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];
}

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

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

NSMutableOrderedSet* tempSet = [self mutableOrderedSetValueForKey:@"subitems"];
      [tempSet addObject:value];
[tempSet addObject:value];
这样就不需要在bug修复后对生成的代码进行分类,这些分类可能会与Apple的解决方案发生冲突


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

如果您使用的是mogenerator,则

[parentObject add<Child>sObject:childObject];
list.addItemsObject(item)
只需使用:

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

我也有同样的问题,但只是当我尝试了与我一直在做的不同的事情时。我看不到子项的代码,但我会假设它有一个指向子项的反向链接。让我们将此reveres链接称为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;

其效果是,它使用了苹果自己的代码,而且简单明了。此外,该集合将自动添加到,并更新所有观察者。没问题。

是的,这绝对是一个核心数据错误。不久前,我编写了一个基于ObjC运行时的修复程序,但当时我认为它很快就会得到修复。无论如何,没有这样的运气,所以我把它发布在GitHub上。解决所有实体上的问题:

[managedObjectModel kc_generateOrderedSetAccessors];
特别是一个实体:

[managedObjectModel kc_generateOrderedSetAccessorsForEntity:entity];
还是就一个人 关系:

[managedObjectModel kc_generateOrderedSetAccessorsForRelationship:relationship];

我找到了一个适合我的修复程序。我只是替换这个:

[item addSubitemsObject:subItem];
为此:

item.subitemsObject = subItem;

我通过谷歌搜索错误消息发现了这个问题,我只是想指出,我在不使用有序集的情况下,以一种稍微不同的方式遇到了这个错误。这不是对给定问题的完全回答,但我将它发布在这里,以防它对其他在搜索时偶然发现此问题的人有所帮助

我正在添加一个新的模型版本,并向现有模型添加了一些关系,并且自己在头文件中定义了add*Object方法。当我试着给他们打电话时,我发现了上面的错误

在回顾了我的模型之后,我意识到我愚蠢地忘记了勾选to Many Relationship复选框


因此,如果您遇到这种情况,并且没有使用有序集,请仔细检查您的模型

我已经追踪到了这个bug。它出现在willChangeValueForKey:with设置变异:UsingObject:

这个电话引发了一系列通知,这些通知可能很难跟踪,当然,对一个响应者的更改可能会对另一个响应者产生影响,我怀疑这就是为什么苹果没有采取任何行动的原因

但是,在集合中是可以的,只有在OrderedSet上的集合操作会发生故障。这意味着只有四种方法需要改变。因此,我所做的只是将集合操作转换为它们的等效数组操作。这些工作非常完美,开销最小,但却是必要的

在关键级别上,此解决方案确实存在一个关键缺陷;如果您正在添加对象,并且其中一个对象已经存在,那么它要么没有添加,要么移动到有序列表的后面,我不知道是哪个。在这两种情况下,当我们到达didChange时,对象的预期有序索引与预期的不同。这可能会破坏某些人的应用程序,但不会影响我的应用程序,因为我只会添加新对象,或者在添加它们之前确认它们的最终位置

- (void)addChildrenObject:(BAFinancialItem *)value {
    if ([self.children containsObject:value]) {
        return;
    }
    NSIndexSet * indexSet = [NSIndexSet indexSetWithIndex:self.children.count];
    [self willChange:NSKeyValueChangeInsertion valuesAtIndexes:indexSet forKey:ChildrenKey];
    [[self primitiveValueForKey:ChildrenKey] addObject:value];
    [self didChange:NSKeyValueChangeInsertion valuesAtIndexes:indexSet forKey:ChildrenKey];
}

- (void)removeChildrenObject:(BAFinancialItem *)value {
    if (![self.children containsObject:value]) {
        return;
    }
    NSIndexSet * indexSet = [NSIndexSet indexSetWithIndex:[self.children indexOfObject:value]];
    [self willChange:NSKeyValueChangeRemoval valuesAtIndexes:indexSet forKey:ChildrenKey];
    [[self primitiveValueForKey:ChildrenKey] removeObject:value];
    [self didChange:NSKeyValueChangeRemoval valuesAtIndexes:indexSet forKey:ChildrenKey];
}

- (void)addChildren:(NSOrderedSet *)values {
    if ([values isSubsetOfOrderedSet:self.children]) {
        return;
    }
    NSIndexSet * indexSet = [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(self.children.count, values.count)];
    [self willChange:NSKeyValueChangeInsertion valuesAtIndexes:indexSet forKey:ChildrenKey];
    [[self primitiveValueForKey:ChildrenKey] unionOrderedSet:values];
    [self didChange:NSKeyValueChangeInsertion valuesAtIndexes:indexSet forKey:ChildrenKey];
}

- (void)removeChildren:(NSOrderedSet *)values {
    if (![self.children intersectsOrderedSet:values]) {
        return;
    }
    NSIndexSet * indexSet = [self.children indexesOfObjectsPassingTest:^BOOL(id obj, NSUInteger idx, BOOL *stop) {
        return [values containsObject:obj];
    }];
    [self willChange:NSKeyValueChangeRemoval valuesAtIndexes:indexSet forKey:ChildrenKey];
    [[self primitiveValueForKey:ChildrenKey] minusOrderedSet:values];
    [self didChange:NSKeyValueChangeRemoval valuesAtIndexes:indexSet forKey:ChildrenKey];
}
当然,还有一个更简单的解决方案。具体如下:

- (void)addChildrenObject:(BAFinancialItem *)value {
    if ([self.children containsObject:value]) {
        return;
    }
    [self insertObject:value inChildrenAtIndex:self.children.count];
}

- (void)removeChildrenObject:(BAFinancialItem *)value {
    if (![self.children containsObject:value]) {
        return;
    }
    [self removeObjectFromChildrenAtIndex:[self.children indexOfObject:value]];
}

- (void)addChildren:(NSOrderedSet *)values {
    if ([values isSubsetOfOrderedSet:self.children]) {
        return;
    }
    [self insertChildren:values atIndexes:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(self.children.count, values.count)]];
}

- (void)removeChildren:(NSOrderedSet *)values {
    if (![self.children intersectsOrderedSet:values]) {
        return;
    }
    [self removeChildrenAtIndexes:[self.children indexesOfObjectsPassingTest:^BOOL(id obj, NSUInteger idx, BOOL *stop) {
        return [values containsObject:obj];
    }]];
}

我只是对这个问题感到不满,并使用了比这里概述的其他实现简单得多的实现来解决它。我只是在不使用子类的情况下,利用NSManagedObject上可用的方法来处理关系

将实体插入到数据集关系的示例实现如下所示:

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

这非常有效,这也是我在转到NSManagedObject子类之前所使用的方法。

如果通过将父对象设置为子对象来链接父对象和子对象,而不是通过相反的方式来链接父对象和子对象,似乎可以在不崩溃的情况下工作

因此,如果你这样做:

而不是

[parentObject add<Child>sObject:childObject];
list.addItemsObject(item)

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

我认为每个人都忽略了真正的问题。它不在访问器方法中,而是在以下事实中:NSOrderedSet不是NSSet的子类。因此,当使用有序集作为参数调用-interSectsSet:时,它将失败

NSOrderedSet* setA = [NSOrderedSet orderedSetWithObjects:@"A",@"B",@"C",nil];
NSSet* setB = [NSSet setWithObjects:@"C",@"D", nil];

 [setB intersectsSet:setA];
与***-[NSSet intersectsSet:]一起失败:set参数不是NSSet

看来修复方法是更改set操作符的实现,以便它们透明地处理类型。没有理由认为-intersectsSet:应该使用有序集或无序集

异常发生在更改通知中。大概在处理反向关系的代码中。因为只有当我设置一个相反的关系时才会发生

下面这句话帮了我的忙

@implementation MF_NSOrderedSetFixes

+ (void) fixSetMethods
{
    NSArray* classes = [NSArray arrayWithObjects:@"NSSet", @"NSMutableSet", @"NSOrderedSet", @"NSMutableOrderedSet",nil];

    [classes enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
        NSString* name = obj;
        Class aClass = objc_lookUpClass([name UTF8String]);
        [MF_NSOrderedSetFixes fixMethodWithSetArgument:@selector(intersectsSet:) forClass:aClass];
        [MF_NSOrderedSetFixes fixMethodWithSetArgument:@selector(isSubsetOfSet:) forClass:aClass];
    }];
}

typedef BOOL (*BoolNSetIMP)(id _s,SEL sel, NSSet*);

/*
    Works for all methods of type - (BOOL) method:(NSSet*) aSet
*/
+ (void) fixMethodWithSetArgument:(SEL) aSel forClass:(Class) aClass 
{
    /* Check that class actually implements method first */
    /* can't use get_classInstanceMethod() since it checks superclass */
    unsigned int count,i;
    Method method = NULL;
    Method* methods = class_copyMethodList(aClass, &count);
    if(methods) {
        for(i=0;i<count;i++) {
            if(method_getName(methods[i])==aSel) {
                method = methods[i];
            }
        }
        free(methods);
    }
    if(!method) {
        return;
    }

   // Get old implementation
   BoolNSetIMP originalImp  = (BoolNSetIMP) method_getImplementation(method);
   IMP newImp = imp_implementationWithBlock(^BOOL(NSSet *_s, NSSet *otherSet) {
        if([otherSet isKindOfClass:[NSOrderedSet class]]) {
            otherSet = [(NSOrderedSet*)otherSet set];
        }
        // Call original implementation
        return originalImp(_s,aSel,otherSet);
    });
    method_setImplementation(method, newImp);
}
@end
说明:您应该使用访问代理可变集或有序集

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

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

我刚刚在Swift Xcode 6.1.1中遇到问题

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


希望对您有所帮助。

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

下面是一个示例类的完整解决方案,它尽可能依赖默认访问器

假设我们有一个包含已订购项目的列表

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

item.list = list
而不是

[parentObject add<Child>sObject:childObject];
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,你也可以做同样的事情,因为这是我第一次想到的:

我解决这个问题的方法是将逆运算设置为无逆运算,我不知道为什么,可能是苹果的Bug。

我很确定它终于出现了

SWIFT中正确答案的更好版本

var tempSet = NSMutableOrderedSet()
if parent!.subItems != nil {
    tempSet = NSMutableOrderedSet(orderedSet: parent!.subItems!)
}

tempSet.add(newItem)
parent!.subItems = tempSet

我也看到了同样的问题。有希望地

很快就会修好的。尽管目前直接使用可变有序集是一个简单的解决方法。注意:我使用的是mogenerator,但我假设它在内部使用相同的Apple generator来生成这部分代码。这几乎是2年!你会在iOS 7中修复它吗,苹果?--我只想和那些想知道这个bug是否仍然存在的人分享:是的,确实存在。现在已经快两年了,这仍然是所有xcode 5开发人员预览中的一个问题。如果您使用适当的KVC访问器,您是否仍然看到这个问题?i、 mutableOrderedSetValueForKey:在Mavericks上似乎仍然是一个问题。你的代码片段正是我解决这个问题所需要的。希望苹果最终能解决这个问题,但到目前为止,我还没有发现使用你的方法有任何问题。我在尝试实施这项工作时遇到了这个错误。。[\uu NSArrayI isEqualToSet:]:无法识别的选择器已发送到实例。。。这通常来自一个已发布的项目,但找不到在哪里有人遇到它?@DerekH isEqualToSet是一个只有NSSet拥有的方法,所以我猜您在返回NSManagedObject之前已经转换、创建或将指针视为NSArray,如果有任何原因调用IseQualTorderedSet以确定该集合是否需要更改或保持原样,则应使用该选项。@MarkAmery Tested。已证实的动态setter self.subitems确实发送通知。所以JLust解决方案是正确的。这是一个很好的答案,但效率低下。复制整个有序集,修改,然后将其复制回。其效果不仅是对已排序集的点击,而且会发出通知,每次更改已排序集时,其全部内容都会更改!例如,如果此有序集用于UITable,则可能会对更新产生严重影响。在我的解决方案中,我已经给出了错误的确切来源,并展示了一种更有效的绕过错误的方法。错误ID是10114310。报告于2011年9月13日发布,但截至2012年1月15日,仍然开放。更新:今天2012年5月11日,在我2011年9月13日的报告发布241天后,漏洞10114310仍然存在。难以置信。我刚刚在WWDC的一次CoreData实验室会议上与一位苹果工程师提出了这个问题。他们承认这个问题,而且这是一个真正的bug,从我所看到的情况来看,它具有关键的地位,但当然,他们没有承诺何时修复它。我认为它不会在iOS6/山狮中修复。我想最好再复制一下这个雷达。目前大约有25个dup,越多越好!今天刚刚检查过,它仍然存在于iOS 7 GM/OMG中!我简直不敢相信…更新:797天,两个新的主要iOS版本,和无数的Xcode版本已经过去,因为我填补了错误10114310。它仍然是开放的。难以置信。对于CoreData返回或获取SensorDeredSet对象,必须满足多个条件,正如这个问题所示。当人们共享我的代码时,我看到的最常见的错误是开发人员没有运行Lion。snowleopard上没有DeredSets框架。但是,是的,我没有看到这失败,虽然我不确定这是最好的性能。我猜这会占用整个集合并替换它,而不仅仅是插入所需的记录。不能像重构文本字符串那样容易。如果使用代码,编译器可以键入check self.subitems。@logancautrell yes这是正确的。它取决于特定用例的优先级。一般来说,我关注于节省资源,尤其是在这种情况下,因为这只是一种解决方法NSStringFromSelector@selectorsubitems不过:碰撞类型是什么?”RemoveObjectFromSubItemsIndex’不会删除这些子项,它们仍然存在于您的存储中,这只是删除对象之间关系的方法。kItemsKey是一个常量,添加该常量只是为了方便KVO方法调用。这是一个有序关系的名字,你在写你的方法,这就是我所认为的。谢谢但我的问题是,数据并没有用这些方法保存到数据库中。!!!!!!!!!只需复制代码并更改方法名称,它就可以完美地工作!!!这是最快的答案。这很好,但是创建有序集的临时副本是不必要的。罪魁祸首是willChangeValueForKey:withSetMutation:UsingObject,您已经成功避免了它。之后,只需根据需要使用[[self-primitiveValueForKey:ChildrenKey]unionOrderedSet:values]或[[self-primitiveValueForKey:ChildrenKey]minusOrderedSet:values]。有关详细信息,请参阅我的答案。因为mogenerator会处理您必须编写的额外代码,并且只允许访问基础set对象。看起来修复程序刚刚提交,这意味着mogenerator将生成正确的实体。。。我正在使用mogenerator,但仍然存在错误。这会导致以下错误:“[valueForUndef

inedKey:]:该类不符合关键子项的键值编码。“尽管这一问题没有列入苹果公司的已知问题中,我仍然感到非常恼火,但我已经打开了一个雷达,因为它显然是徒劳的姿态,这个解决方案对我来说完美无瑕。但愿我早点看到这个答案;我一直在使用投票率最高的答案,直到最近我做了一些挖掘,并最终实现了您在这里所看到的:为什么addObject:调用了两次?我想知道这是否会与苹果的真正修复程序冲突?这不应该与苹果的修复程序冲突,因为它的目的是无论如何都要覆盖苹果的实现。如果苹果真的修复了这个问题,也许我会添加一个-BOOLkc_needsOrderedSetAccessorFix;或者检查Foundation/iOS版本的东西。CocoaPods主repo中已经有一个KCOrderedAccessorFix.podspec。因此,为了将其链接到您的项目,您可以简单地将pod“KCOrderedAccessorFix”添加到您的pod文件中。这在iOS 8中存在一些问题。iOS9上的objc_msg_sendOn的方法签名不正确。它工作正常,干得好!这是有史以来最好的解决方案,无需更改代码中的任何内容!这很好。它解决了整个问题,并使其保持有序。仍然疯狂的是,这个错误仍然存在。这个答案的另一个好处是,如果重新生成核心数据模型,就不必重写错误修复。谢谢看看我的另一个答案。我更详细地跟踪了这个bug。这仍然是最简单的方法,但另一种方法是最好的,因为它打开了更多的可能性。哇!最后谢谢尝试了其他代码,但出现了错误,在[self-didChange:NSKeyValueChangeInsertion ValuesIndexes:indexSet-forKey:ChildrenKey]发送了关于错误类型的信息;将此代码移动到类别中是很好的一点。但我们仍然需要使用will/setPrimitiveValue/didChange调用(如@Dmitry Makarenko answer中的调用)来实现实际的添加/删除。可惜其他人似乎忽略了这个答案,这显然是最好的解决方案。这个解决方案比使用orderedSetWithOrderedSet生成本地集的解决方案具有更好的性能。当您拥有大型数据集时,这会带来很大的开销。更简单的解决方案似乎只是初始版本的重构版本,其中没有显示方法。我仍然在addChildren中看到崩溃:**由于未捕获的异常“NSInvalidArgumentException”而终止应用程序,原因:'-[TrackHistory insertTrackpoints:atIndexes:]:无法识别的选择器发送到实例0x1702b1b20'@OwenGodfrey以获得更简单的解决方案,您在哪里实现这些方法?我收到一个异常:[Parent insertObject:inChildrenAtIndex:]未识别的选择器发送到实例0x618000AC480。您的变量是大写P的父变量吗?这是否意味着您正在调用类Parent,或者您是否有一个名为Parent的实例变量?如果我的类是Parent,那么我在Parent的底部实现了这个方法,但是你需要在一个实例上调用它,这个实例很可能被命名为Parent,并带有小写的p,因为它们不是类方法。当双方都太多时,这没什么好处。那么就没有明确的父子关系了。公平地说,文档还说:或者自动生成的关系mutator方法之一请参见动态生成的访问器方法:好的好的。。。你说得对。那么,假设这是最简单的工作方式……那么,如果我不能实现其他修复,我应该怎么做来修复它?