Исключение, вызванное генерируемыми NSOrderedSet

В моем приложении Lion у меня есть эта модель данных:

введите описание изображения здесь

subitems отношения внутри Item упорядочены .

Xcode 4.1 (assembly 4B110) создал для меня файл Item.h , Item.m , SubItem.h и SubItem.h .

Вот содержание (автогенерированное) Item.h :

 #import  #import  @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 

Как вы можете видеть, class 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 дней из моего отчета об ошибке, сегодня (1 августа 2016 года) Apple написала мне следующее: «Пожалуйста, проверьте эту проблему с последней версией бета-версии iOS 10 и обновите свой отчет об ошибке на странице bugreport.apple.com с результатами». , Будем надеяться, что это подходящее время 🙂

Я воспроизвел вашу настройку как с вашей моделью данных, так и с моей собственной версией с разными именами. Я получил ту же ошибку в обоих случаях.

Похож на ошибку в автогенерированном коде Apple.

Я согласен, что здесь может быть ошибка. Я изменил реализацию установки объекта добавления, чтобы правильно добавить NSMutableOrderedSet.

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

Перенос набора в self.subitems обеспечит отправку уведомлений Will / DidChangeValue.

Я решил улучшить решение, выполнив все необходимые методы:

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

Да, это определенно ошибка Core Data. Я написал исправление на основе ObjC-Runtime некоторое время назад, но в то время, когда я решил, что скоро будет исправлено. Во всяком случае, нет такой удачи, поэтому я разместил ее на GitHub как KCOrderedAccessorFix . Работайте над проблемой на всех ваших объектах:

 [managedObjectModel kc_generateOrderedSetAccessors]; 

В частности, одна организация:

 [managedObjectModel kc_generateOrderedSetAccessorsForEntity:entity]; 

Или просто для одного отношения:

 [managedObjectModel kc_generateOrderedSetAccessorsForRelationship:relationship]; 

Вместо того, чтобы делать копию, я предлагаю использовать accessor в NSObject для доступа к NSMutableOrderedSet отношений.

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

например, примечания о выпуске основных данных для iOS v5.0 относятся к этому.

В коротком тесте он работал в моем приложении.

Я отследил ошибку. Это происходит в willChangeValueForKey:withSetMutation:usingObjects:

Этот вызов вызывает цепочку уведомлений, которые могут быть трудно отследить, и, конечно, изменения для одного ответчика могут иметь последствия для другого, и я подозреваю, почему Apple ничего не сделала.

Тем не менее, все в порядке в Set, и это приводит к сбою в работе только заданий Set на OrderedSet. Это означает, что необходимо изменить только четыре метода. Поэтому все, что я сделал, было преобразование операций Set в их эквивалентные операции массива. Они работают отлично и минимально (но обязательно) накладные расходы.

На критическом уровне это решение действительно страдает от одного критического недостатка; если вы добавляете объекты и один из уже существующих объектов, то он либо не добавлен, либо перемещен в конец упорядоченного списка (я не знаю, какой из них). В любом случае ожидаемый упорядоченный индекс объекта к моменту поступления в 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]; }]]; } 

Apple docs To Many Relations говорит: вам нужно получить доступ к прокси-мутируемому набору или упорядоченному набору, используя

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

Изменение этого набора добавит или удалит отношения к вашему управляемому объекту. Доступ к изменяемому упорядоченному набору с использованием accessor с помощью [] или. нотация ошибочна и не удастся.

Получив ту же ошибку, решение @LeeIII работало для меня (спасибо!). Я предлагаю немного изменить его:

  • используйте категорию object-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 

Если вы используете mogenerator, то вместо

 [parentObject addsObject:childObject]; 

просто используйте:

 [[parent object sSet] addObject:childObject]; 

Лично я только что заменил вызовы на сгенерированные CoreData методы прямыми вызовами метода, описанными в другом решении @Stephan:

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

Это устраняет необходимость в категориях, которые могут впоследствии конфликтовать с решением Apple от сгенерированного кода при исправлении ошибки.

У этого есть дополнительный плюс того, чтобы быть официальным способом сделать это!

Кажется, что если вы связываете родителя с дочерним элементом, устанавливая родителя для ребенка, а не наоборот, он работает без сбоев.

Поэтому, если вы это сделаете:

 [child setParent:parent] 

вместо

 [parent setChildObects:child] 

Он должен работать, по крайней мере, он работает на iOS 7 и не имел никаких проблем с отношениями.

У меня была та же проблема, но только когда я пробовал что-то другое, чем то, что я делал. Я не вижу код для subItem, но я предполагаю, что он имеет обратную ссылку на элемент. Позволяет называть эту ссылку 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; 

Эффект заключается в том, что он использует собственный код Apple, и он прост и чист. Кроме того, набор автоматически добавляется, и все наблюдатели обновляются. Нет проблем.

Я просто свалил эту проблему и решил ее, используя гораздо более простую реализацию, чем другие, описанные здесь. Я просто использую методы, доступные в NSManagedObject для работы с отношениями, когда не используются подclassы.

Пример реализации для вставки объекта в отношения NSOrderedSet будет выглядеть так:

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

Это работает отлично, и это то, что я использовал до того, как перешел в подclassы NSManagedObject .

Эта проблема возникла при переносе проекта с Objective-C на Swift 2 с XCode 7 . Этот проект работал, и по уважительной причине: я использовал MOGenerator, у которого были методы замены, чтобы исправить эту ошибку. Но не все методы требуют замены.

Итак, вот полное решение с примерным classом, максимально использующим аксессоры по умолчанию.

Допустим, у нас есть список с упорядоченными элементами

Сначала быстрая победа, если у вас есть отношения «один-ко-многим», проще всего просто:

 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, вы можете сделать то же самое, потому что именно здесь я получил идею в первую очередь 🙂

Я согласен, что здесь может быть ошибка. Я изменил реализацию добавления объекта> setter, чтобы правильно добавить NSMutableOrderedSet.

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

Переназначение набора для self.subitems обеспечит отправку уведомлений Will / DidChangeValue.

Leelll, вы уверены, что после такой пользовательской настройки значений NSMutableOrderedSet, хранящихся в этом наборе, будут правильно сохранены в базе данных CoreData? Я не проверял это, но похоже, что CoreData ничего не знает о NSOrderedSet и ожидает контейнер NSSet как для многих.

Я думаю, что у всех отсутствует реальная проблема. Это не в методах доступа, а в том, что NSOrderedSet не является подclassом 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

Похоже, что исправление заключается в том, чтобы изменить реализацию операторов set, чтобы они прозрачно обрабатывали типы. Нет причин, по которым a -intersectsSet: должен работать либо с упорядоченным, либо с неупорядоченным набором.

Исключение происходит в уведомлении об изменении. Предположительно в коде, который обрабатывает обратную связь. Так как это происходит, если я устанавливаю обратную связь.

The following did the trick for me

 @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 

I just got the problem in Swift (Xcode 6.1.1).

The answer was DO NOT CODE ANY METHOD OR ADDITIONAL THINGS in your NSManagedObject subclasses. I think it is a compilator mistake. Very strange bug ..

Hope it helps ..

I solved this problem by set the inverse to No Inverse, I don’t know why, Maybe there is Apple Bug. введите описание изображения здесь

I have the same situation with an item called “signals” instead of “subitems”. The solution with tempset works in my testing. Further, I had a problem with the removeSignals: method. This override seems to work:

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

If there is a better way to do this, please let me know. My values input is never more than 10 -20 items so performance isn’t much of a concern – nonetheless please point out anything relevant.

Благодаря,

Damien

I found this question by googling for the error message, and just wanted to point out that I ran into this error in a slightly different way (not using ordered sets). This isn’t quite an answer to the given question, but I’m posting it here just in case it is helpful to anyone else who stumbles across this question while searching.

I was adding a new model version, and added some relationships to existing models, and defined the add*Object methods in the header file myself. When I tried to call them, I got the error above.

After reviewing my models, I realized I had stupidly forgotten to check the “To-Many Relationship” checkbox.

So if you’re running into this and you’re not using ordered sets, double check your model.

I found a fix for this bug that works for me. I just replace this:

 [item addSubitemsObject:subItem]; 

with this:

 item.subitemsObject = subItem; 

I found using the method by LeeIII worked, but on profiling found it was drastically slow. It took 15 seconds to parse 1000 items. Commenting out the code to add the relationship turned 15 seconds into 2 seconds.

My workaround (which is faster but much more ugly) involves creating a temporary mutable array then copying into the ordered set when all the parsing is done. (this is only a performance win if you are going to add many relationships).

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

I hope this help someone else!

Robert,

I agree your answer will work for this, but keep in mind that there is an automatically created method for adding a whole set of values to a relationship already. Apple’s Documentation ( as seen here under the “To-many Relationships” section or here under the “Custom To-Many Relationship Accessor Methods” section) implements them this way:

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

You could easily compile your set of relationships outside of core data and then add them all at once using this method. It might be less ugly than the method you suggested 😉

I’m quite sure it is finally fixed in iOS 10 beta 6 !

Better version of the correct answer in SWIFT

 var tempSet = NSMutableOrderedSet() if parent!.subItems != nil { tempSet = NSMutableOrderedSet(orderedSet: parent!.subItems!) } tempSet.add(newItem) parent!.subItems = tempSet 
  • Xcode 4 - создать выходной каталог
  • Xcode 4 - «Архив» выделен серым цветом?
  • Xcode 4 не может найти общедоступные файлы заголовков из зависимости статической библиотеки
  • путь поиска заголовка в XCode 4
  • Как очистить кеши и очистить все цели Xcode 4 и более поздние версии
  • Каков правильный способ настройки рабочих пространств XCode 4 для создания зависимостей, когда это необходимо?
  • Добавление файлов в отдельные объекты в Xcode 4
  • Разница между фреймворком и статической библиотекой в ​​xcode4 и как их называть
  • AVAudioPlayer не воспроизводит звук
  • XCode 4 зависает при «Присоединении к (имя приложения)»
  • Как я могу использовать файлы .xcconfig в Xcode 4?
  • Давайте будем гением компьютера.