Excepción arrojada en accesadores NSOrderedSet generados

En mi aplicación Lion, tengo este modelo de datos:

enter image description here

Los subitems relación dentro de Item están ordenados .

Xcode 4.1 (comstackción 4B110) ha creado para mí el archivo Item.h , Item.m , SubItem.h SubItem.h .

Aquí está el contenido (autogenerado) de 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 

Y aquí está el contenido (autogenerado) de Item.m :

 #import "Item.h" #import "SubItem.h" @implementation Item @dynamic name; @dynamic subitems; @end 

Como puede ver, la clase Item ofrece un método llamado addSubitemsObject: Lamentablemente, al tratar de usarlo de esta manera:

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

este error aparece:

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

¿Me puedes ayudar?

Actualizar:

Luego de solo 1.787 días desde mi informe de errores, hoy (1 de agosto de 2016) Apple me escribió esto: “Verifique este problema con la última versión beta de iOS 10 y actualice su informe de errores en bugreport.apple.com con sus resultados”. . Esperemos que este sea el momento adecuado 🙂

Reproduje tu configuración tanto con tu modelo de datos como uno con nombres diferentes. Tengo el mismo error en ambos casos.

Parece un error en el código autogenerado de Apple.

Estoy de acuerdo en que puede haber un error aquí. Modifiqué la implementación del setter de objetos add para anexarlo correctamente a un NSMutableOrderedSet.

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

La reasignación del conjunto a self.subitems garantizará que se envíen las notificaciones de Will / DidChangeValue.

Decidí mejorar la solución implementando todos los métodos necesarios:

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

Sí, esto es definitivamente un error de Core Data. Escribí un arreglo basado en ObjC-Runtime hace un tiempo, pero en ese momento pensé que se solucionaría pronto. De todos modos, no tuve suerte, así que lo publiqué en GitHub como KCOrderedAccessorFix . Solucione el problema en todas sus entidades:

 [managedObjectModel kc_generateOrderedSetAccessors]; 

Una entidad en particular:

 [managedObjectModel kc_generateOrderedSetAccessorsForEntity:entity]; 

O solo por una relación:

 [managedObjectModel kc_generateOrderedSetAccessorsForRelationship:relationship]; 

En lugar de hacer una copia, sugiero que use el acceso en NSObject para obtener acceso al NSMutableOrderedSet de las relaciones.

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

por ejemplo, las Notas de versión de Core Data para iOS v5.0 se refieren a esto.

En una prueba corta funcionó en mi aplicación.

He rastreado el error. Ocurre en willChangeValueForKey:withSetMutation:usingObjects:

Esta llamada desencadena una cadena de notificaciones que pueden ser difíciles de rastrear y, por supuesto, los cambios en un respondedor pueden tener implicaciones para otro, y sospecho que es por eso que Apple no ha hecho nada.

Sin embargo, está bien en Set y solo las operaciones Set en un OrderedSet que funcionan mal. Eso significa que solo hay cuatro métodos que necesitan ser alterados. Por lo tanto, todo lo que hice fue convertir las operaciones de Set a sus operaciones de Array equivalentes. Estos funcionan perfectamente y son mínimos (pero necesarios) gastos generales.

En un nivel crítico, esta solución sufre de un defecto crítico; si está agregando objetos y uno de los objetos ya existe, entonces no se agrega ni se mueve al final de la lista ordenada (no sé cuál). En cualquier caso, el índice esperado del objeto en el momento en que llegamos a didChange es diferente de lo que se esperaba. Esto puede romper las aplicaciones de algunas personas, pero no afecta al mío, ya que solo agrego nuevos objetos o confirmo sus ubicaciones finales antes de agregarlas.

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

Por supuesto, hay una solución más fácil. es como sigue;

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

La documentación de Apple To Many Relations dice: debe acceder al conjunto mutable de proxy o al conjunto ordenado usando

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

La modificación de este conjunto agregará o eliminará las relaciones con su objeto administrado. Accediendo al conjunto ordenado mutable utilizando el acceso, ya sea con [] o. la notación es incorrecta y fallará.

Recibí el mismo error, la solución @LeeIII funcionó para mí (¡gracias!). Sugiero modificarlo ligeramente:

  • use la categoría objective-c para almacenar el nuevo método (para que no perdamos nuestro método si el ítem es generado nuevamente)
  • compruebe si ya tenemos un conjunto mutable

Contenido de 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 

Si está utilizando mogenerator, entonces en lugar de

 [parentObject addsObject:childObject]; 

simplemente use:

 [[parent object sSet] addObject:childObject]; 

Personalmente acabo de reemplazar las llamadas a los métodos generados por CoreData con llamadas directas al método como se describe en otra solución por @Stephan:

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

Esto elimina la necesidad de categorías que luego podrían entrar en conflicto con una solución de Apple al código generado cuando se soluciona el error.

¡Esto tiene la ventaja adicional de ser la forma oficial de hacerlo!

Parece que si vincula el padre con el hijo estableciendo el padre para el hijo y no al revés, funciona sin fallar.

Entonces si lo haces:

 [child setParent:parent] 

en lugar de

 [parent setChildObects:child] 

Debería funcionar, al menos funciona en iOS 7 y no tuvo ningún problema con la relación.

He tenido el mismo problema, pero solo cuando intenté algo diferente a lo que había estado haciendo. No puedo ver el código de subItem, pero supongo que tiene un enlace inverso al elemento. Vamos a llamar a este enlace reveres, “parentItem”, entonces la solución más fácil es esta:

 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; 

El efecto es que utiliza el propio código de Apple y es simple y limpio. Además, el conjunto se agrega automáticamente y todos los observadores se actualizan. No hay problema.

Simplemente me encontré con este problema y lo resolví usando una implementación mucho más simple que las otras descritas aquí. Simplemente utilizo los métodos disponibles en NSManagedObject para tratar las relaciones cuando no uso subclases.

Una implementación de ejemplo para insertar una entidad en una relación NSOrderedSet se vería así:

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

Esto funciona perfectamente, y es lo que estaba usando antes de NSManagedObject subclases NSManagedObject .

Se me ocurrió este problema al migrar un proyecto de Objective-C a Swift 2 con XCode 7 . Ese proyecto solía funcionar, y por una buena razón: estaba usando MOGenerator, que tenía métodos de reemplazo para solucionar este error. Pero no todos los métodos requieren un reemplazo.

Así que aquí está la solución completa con una clase de ejemplo, confiando en los accesos predeterminados tanto como sea posible.

Digamos que tenemos una lista con elementos ordenados

Primero una ganancia rápida si tiene una relación uno / a-muchos, lo más fácil es hacer:

 item.list = list 

en lugar de

 list.addItemsObject(item) 

Ahora, si eso no es una opción , esto es lo que puedes hacer:

 // 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 

Por supuesto, si está utilizando Objective-C, puede hacer exactamente lo mismo, ya que es aquí donde surgió la idea 🙂

Estoy de acuerdo en que tal vez haya un error aquí. Modifiqué la implementación del objeto add> setter para anexarlo correctamente a un NSMutableOrderedSet.

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

Al reasignar el conjunto a self.subitems se asegurará de que se envíen las notificaciones Will / DidChangeValue>.

Leelll, ¿está seguro de que después de dicha configuración personalizada de NSMutableOrderedSet, los valores almacenados en ese conjunto se guardarán correctamente en la base de datos por CoreData? No lo verifiqué, pero parece que CoreData no sabe nada sobre NSOrderedSet y espera que NSSet sea un contenedor de relaciones.

Creo que a todos les falta el problema real. No está en los métodos de acceso, sino en el hecho de que NSOrderedSet no es una subclase de NSSet . Entonces cuando se llama a -interSectsSet: con un conjunto ordenado como argumento, falla.

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

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

Parece que la solución es cambiar la implementación de los operadores establecidos para que manejen los tipos de forma transparente. No hay razón por la cual un -intersectsSet: debería funcionar con un conjunto ordenado o no ordenado.

La excepción ocurre en la notificación de cambio. Presumiblemente en el código que maneja la relación inversa. Como solo ocurre si establezco una relación inversa.

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 comstacktor mistake. Very strange bug ..

Espero eso ayude ..

I solved this problem by set the inverse to No Inverse, I don’t know why, Maybe there is Apple Bug. enter image description here

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.

Gracias,

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

con este:

 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