I've got a Contact entity with a one-to-many relationship to another entity that stores information about email addresses (it's called TypedValue because it also includes the email type, like personal, work, etc).
This relationship (called "emails," naturally), is also ordered, so that I can display a contact's list of email addresses in a table view, and allow the user to delete or modify each one. As far as I can tell, they need to be ordered so that I can tell which one is being removed/modified: for example, if the user taps the delete button in row 1, the second email address should be removed from the relationship. Without being ordered, I wouldn't know which one to remove.
When generating the NSManagedObject subclass, I get an NSOrderedSet property on the class, and CoreData helpfully provided some accessors in the .h file:
@interface Contact (CoreDataGeneratedAccessors)
- (void)insertObject:(TypedValue *)value inEmailsAtIndex:(NSUInteger)idx;
- (void)removeObjectFromEmailsAtIndex:(NSUInteger)idx;
- (void)insertEmails:(NSArray *)value atIndexes:(NSIndexSet *)indexes;
- (void)removeEmailsAtIndexes:(NSIndexSet *)indexes;
- (void)replaceObjectInEmailsAtIndex:(NSUInteger)idx withObject:(TypedValue *)value;
- (void)replaceEmailsAtIndexes:(NSIndexSet *)indexes withEmails:(NSArray *)values;
- (void)addEmailsObject:(TypedValue *)value;
- (void)removeEmailsObject:(TypedValue *)value;
- (void)addEmails:(NSOrderedSet *)values;
- (void)removeEmails:(NSOrderedSet *)values;
@end
My problem is that only some of these work. addEmailsObject:
works just fine, but the remove or replace methods do not. If I try to replace one of the objects in the set with this call:
// newVal is a properly-built object requested from the managed object context
[self replaceObjectInEmailsAtIndex:index withObject:newVal];
I get a nasty error:
2013-08-16 16:51:19.687 AppName[43837:c07] -[Contact replaceObjectInEmailsAtIndex:withObject:]: unrecognized selector sent to instance 0xa56a800 2013-08-16 16:51:19.694 AppName[43837:c07] * Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[Contact replaceObjectInEmailsAtIndex:withObject:]: unrecognized selector sent to instance 0xa56a800'
From what I've read, this can happen if the object making the call (the Contact object, in this case) is created using regular alloc/init instead of being requested from the managed object context, but I'm doing that part correctly.
I also tried getting a mutable copy of the NSOrderedSet object, to make the updates and then replace the set:
NSMutableOrderedSet *newSet = [self.emails mutableCopy];
[newSet replaceObjectAtIndex:index withObject:newVal];
[self setEmails:newSet];
This didn't throw any errors, but did something wonky: my interface started displaying incorrect values and I'm not sure what happened.
So: what's the correct way to replace and remove objects, if not using the mutators that CoreData purports to provide?