2

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?

Brock Boland
  • 13,320
  • 10
  • 31
  • 36

1 Answers1

1

The auto generated code has a bug which prevents it from working. Your workaround by creating a mutable copy, updating and setting that should work. Any issues in the UI that you see as a result should be a facet of how you're monitoring changes / reloading data to the UI.

Bug reference: here.

Community
  • 1
  • 1
Wain
  • 117,132
  • 14
  • 131
  • 151
  • I was really hoping that I'd just missed something stupid and my situation was somehow different from that other question. Kind of unbelievable that they'd auto-generate broken code here. – Brock Boland Aug 16 '13 at 23:22
  • Follow-up: you were right about the UI issues. I was doing something goofy to provide data to the table, and wasn't updating it correctly. Using the mutable copy seems to be working just fine now. Thanks again! – Brock Boland Aug 17 '13 at 15:46