NSOrderedSet生成的访问器抛出异常

时间:2011-09-12 08:59:25

标签: cocoa core-data xcode4

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

enter image description here

subitems 内的关系Item已订购

Xcode 4.1(版本4B110)为我创建了文件Item.hItem.mSubItem.hSubItem.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

你能帮助我吗?

更新

距离我的错误报告仅1,787天,今天(2016年8月1日)Apple给我写了这样的信息:“请使用最新的iOS 10 beta版本验证此问题,并在bugreport.apple.com上更新您的错误报告结果。“。我们希望这是正确的时间:)

24 个答案:

答案 0 :(得分:263)

我使用您的数据模型和我自己的不同名称重新设置了您的设置。在这两种情况下我都得到了同样的错误。

看起来像Apple的自动生成代码中的错误。

答案 1 :(得分:243)

我同意这里可能存在错误。我已经修改了add object setter的实现,以便正确地追加到NSMutableOrderedSet。

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

将该集重新分配给self.subitems将确保发送Will / DidChangeValue通知。

答案 2 :(得分:111)

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

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

答案 3 :(得分:38)

是的,这绝对是一个核心数据错误。我曾经写过一个基于ObjC-Runtime的修复程序,但当时我认为很快就会修复它。无论如何,没有这样的运气,所以我把它作为KCOrderedAccessorFix发布在GitHub上。解决所有实体的问题:

[managedObjectModel kc_generateOrderedSetAccessors];

特别是一个实体:

[managedObjectModel kc_generateOrderedSetAccessorsForEntity:entity];

或只是为了一个关系:

[managedObjectModel kc_generateOrderedSetAccessorsForRelationship:relationship];

答案 4 :(得分:32)

而不是制作副本我建议使用NSObject中的访问器来访问关系的NSMutableOrderedSet。

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

e.g。 Core Data Release Notes for iOS v5.0指的是这个。

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

答案 5 :(得分:17)

我已经跟踪了这个错误。它出现在willChangeValueForKey:withSetMutation:usingObjects:

此调用引发了一系列可能难以跟踪的通知,当然,对一个响应者的更改可能会对另一个响应者产生影响,我怀疑这是为什么Apple没有做任何事情。

但是,Set中没有问题,只有OrderedSet上的Set操作出现故障。这意味着只需要改变四种方法。因此,我所做的就是将Set操作转换为等效的Array操作。这些工作完美且极少(但必要)开销。

在关键层面上,这种解决方案确实存在一个严重的缺陷;如果你要添加对象并且其中一个对象已经存在,那么它就不会被添加或移动到有序列表的后面(我不知道哪个)。在任何一种情况下,到达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];
    }]];
}

答案 6 :(得分:10)

Apple docs To Many Relations 说:您应该使用

访问代理可变集或有序集
NSMutableOrderedSet * set = [managedObject mutableOrderedSetValueForKey:@"toManyRelation"];

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

答案 7 :(得分:9)

收到同样的错误,@ LieeIII解决方案为我工作(谢谢!)。我建议稍微修改一下:

  • 使用objective-c类别来存储新方法(如果再次生成Item,我们就不会丢失方法)
  • 检查我们是否已经有可变集

Item+category.m的内容:

#import "Item+category.h"

@implementation Item (category)

- (void)addSubitemsObject:(SubItem *)value {
    if ([self.subitems isKindOfClass:[NSMutableOrderedSet class]]) {
        [(NSMutableOrderedSet *)self.subitems addObject:value];
    } else {
        NSMutableOrderedSet* tempSet = [NSMutableOrderedSet orderedSetWithOrderedSet:self.subitems];
        [tempSet addObject:value];
        self.subitems = tempSet;
    }
}

@end

答案 8 :(得分:8)

如果您使用的是mogenerator,则代替

[parentObject add<Child>sObject:childObject];

只需使用:

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

答案 9 :(得分:7)

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

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

这样就不再需要在修复错误时可能与Apple的解决方案冲突的类别与生成的代码冲突。

这有额外的优势,是正式的做法!

答案 10 :(得分:5)

似乎如果您通过将父级设置为子级而将父级与子级相关联而不是相反的方式将其与子级相关联,则不会崩溃。

所以,如果你这样做:

[child setParent:parent]

而不是

[parent setChildObects:child]

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

答案 11 :(得分:3)

使用 XCode 7 将项目从Objective-C迁移到 Swift 2 时,我遇到此问题。该项目曾经工作,并且有充分的理由:我正在使用具有替换方法的MOGenerator来修复此错误。但并非所有方法都需要更换。

所以这里是一个带有示例类的完整解决方案,尽可能依赖于默认访问器。

我们说我们有一个带有订购商品的清单

首先快速获胜如果您有一对多的关系,最简单的就是这样做:

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,你可以做同样的事情,因为这是我首先得到这个想法的地方:))

答案 12 :(得分:3)

我遇到了同样的问题,但只有当我尝试了与我一直在做的事情不同的时候。我看不到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;

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

答案 13 :(得分:3)

  

我同意这里可能存在错误。我已经修改了add对象&gt; setter的实现,以便正确地附加到NSMutableOrderedSet。

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

将该集重新分配给self.subitems将确保发送Will / DidChangeValue通知&gt;。

Leelll,你确定在存储在该集合中的NSMutableOrderedSet值的这种自定义设置之后,CoreData会正确地保存到数据库吗?我没有检查,但看起来CoreData对NSOrderedSet一无所知,并且期望NSSet成为多关系容器。

答案 14 :(得分:3)

我刚刚违反了这个问题,并使用比此处概述的其他更简单的实现来解决它。我只是使用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子类之前我正在使用它。

答案 15 :(得分:2)

我通过将反向设置为No Inverse解决了这个问题,我不知道为什么,也许有Apple Bug。enter image description here

答案 16 :(得分:2)

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

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

希望有所帮助......

答案 17 :(得分:2)

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

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

 [setB intersectsSet:setA];

*** -[NSSet intersectsSet:]: set argument is not an NSSet

失败

看起来修复是改变集合运算符的实现,以便它们透明地处理类型。没有理由-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

答案 18 :(得分:1)

我通过谷歌搜索错误消息找到了这个问题,只是想指出我以稍微不同的方式遇到了这个错误(不使用有序集)。这不是给定问题的答案,但是我在这里发布它是为了防止其他人在搜索时偶然发现这个问题。

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

在查看我的模型后,我意识到我愚蠢地忘记了检查“To-Many Relationship”复选框。

因此,如果您遇到此问题并且未使用有序集,请仔细检查您的模型。

答案 19 :(得分:1)

我对“信号”而非“子项目”的项目具有相同的情况。带有tempset的解决方案适用于我的测试。此外,我遇到了removeSignals:方法的问题。这种覆盖似乎有效:

- (void)removeSignals:(NSOrderedSet *)values {
    NSMutableOrderedSet* tempset = [NSMutableOrderedSet orderedSetWithOrderedSet:self.signals];
    for (Signal* aSignal in values) {
        [tempset removeObject:aSignal];
    }
    self.signals = tempset;
}

如果有更好的方法,请告诉我。我的价值观输入不超过10-20个项目,所以表现并不是很重要 - 尽管如此,请指出任何相关内容。

谢谢,

达明

答案 20 :(得分:1)

我发现这个错误的修复程序对我有用。我只是替换它:

[item addSubitemsObject:subItem];

用这个:

item.subitemsObject = subItem;

答案 21 :(得分:0)

罗伯特,

我同意你的答案对此有用,但请记住,已经有一种自动创建的方法可以将一整套值添加到关系中。 Apple的文档(“To-many Relationships”部分下的as seen here或“Custom To-Many Relationship Accessor Methods”部分下的here以这种方式实现它们:

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

您可以轻松地在核心数据之外编译您的一组关系,然后使用此方法一次性添加它们。它可能不如你建议的方法丑陋;)

答案 22 :(得分:0)

我发现使用LeeIII的方法工作,但是在分析时发现它非常缓慢。解析1000个项目需要15秒。注释掉添加关系的代码将15秒变为2秒。

我的解决方法(速度更快但更难看)涉及创建一个临时可变数组,然后在全部解析完成后复制到有序集中。 (如果您要添加许多关系,这只是表现胜利。)

@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;
    }
}

我希望这可以帮助别人!

答案 23 :(得分:0)

SWIFT正确答案的更好版本

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

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