14

I did some studies on this post. But none of its solution work for me. Let me explain what I did:

enter image description here

It's actually very similar with the mentioned post.

Category.h

@class Category, Item;

@interface Category : NSManagedObject

@property (nonatomic, retain) NSString * name;
@property (nonatomic, retain) NSOrderedSet *items;
@property (nonatomic, retain) Category *parentcategory;
@property (nonatomic, retain) NSSet *subcategories;

@end

@interface Category (CoreDataGeneratedAccessors)

- (void)insertObject:(Item *)value inItemsAtIndex:(NSUInteger)idx;
- (void)removeObjectFromItemsAtIndex:(NSUInteger)idx;
- (void)insertItems:(NSArray *)value atIndexes:(NSIndexSet *)indexes;
- (void)removeItemsAtIndexes:(NSIndexSet *)indexes;
- (void)replaceObjectInItemsAtIndex:(NSUInteger)idx withObject:(Item *)value;
- (void)replaceItemsAtIndexes:(NSIndexSet *)indexes withItems:(NSArray *)values;
- (void)addItemsObject:(Item *)value;
- (void)removeItemsObject:(Item *)value;
- (void)addItems:(NSOrderedSet *)values;
- (void)removeItems:(NSOrderedSet *)values;
- (void)addSubcategoriesObject:(Category *)value;
- (void)removeSubcategoriesObject:(Category *)value;
- (void)addSubcategories:(NSSet *)values;
- (void)removeSubcategories:(NSSet *)values;

@end

In my view controller, I load one of the category:

NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:kEntityCategory];
request.sortDescriptors = [NSArray arrayWithObject:[NSSortDescriptor
                                                    sortDescriptorWithKey:kAttributeCategoryName ascending:YES
                                                    selector:@selector(localizedCaseInsensitiveCompare:)]];

NSError *error = nil;
AppDelegate* appDelegate = (AppDelegate *)[UIApplication sharedApplication].delegate;

NSArray* data = [appDelegate.dataCenter.document.managedObjectContext executeFetchRequest:request error:&error];
if ( data.count > 0)
{
    self.category = [data objectAtIndex:0];
}

I have a button in navigation bar for testing purpose. When it's clicked I'll copy the first item and add to the end.

Item* item = [self.category.items objectAtIndex:0];

[self.category willChangeValueForKey:@"items"];
NSMutableOrderedSet *tempSet = [NSMutableOrderedSet orderedSetWithOrderedSet:self.category.items];
[tempSet addObject: item];
self.category.items = tempSet;
[self.category didChangeValueForKey:@"items"];

The problem is the item is not added to database at all. (I did some testing, for example, I modify the item content. It proves that the database has no problem at all.) But I don't know the reason why the item is not to the database. Can anybody help? Thanks

Community
  • 1
  • 1
Bagusflyer
  • 12,675
  • 21
  • 96
  • 179
  • I can use the NSEntityDescription insertNewObjectForEntityForName to add new Item to the end of the items. But it doesn't solve my problem because I have no way to insert the new item in the middle of my items in category. – Bagusflyer Sep 07 '12 at 03:36

4 Answers4

24

Swift:

let mutableItems = items.mutableCopy() as! NSMutableOrderedSet
mutableItems.addObject(anItem)
items = mutableItems.copy() as! NSOrderedSet

Objective-C:

NSMutableOrderedSet *mutableItems = (NSMutableOrderedSet *)items.mutableCopy;
[mutableItems addObject:anItem];
items = (NSOrderedSet *)mutableItems.copy;
fujianjin6471
  • 5,168
  • 1
  • 36
  • 32
  • 3
    It would be more efficient to have `mutableItems` be a constant using "let." While the ordered set is mutable, the pointer to the object is not going to change so it is better to make constant. – Garrett Mar 30 '15 at 23:21
  • Hey! In swift you should use `let` (as @Garrett said) and force downcast: `let mutableItems = items.mutableCopy() as! NSMutableOrderedSet` `mutableItems.addObject(anItem)` `items = mutableItems.copy() as! NSOrderedSet` – Paul Slm Jul 08 '16 at 05:46
  • 1
    @PaulSlm Updated, Swift is changing so fast! – fujianjin6471 Jul 11 '16 at 01:26
3

The problem solved. There are two problems:

  1. Can't insert/add an existing item
  2. I have a stupid name conflict. So the suggestion in this post is good.

Thanks.

Community
  • 1
  • 1
Bagusflyer
  • 12,675
  • 21
  • 96
  • 179
3

Another way of doing this is with the mutableOrderedSetValueForKey function in NSKeyValueCoding. You could say

owningObject.mutableOrderedSetValueForKey("items").addObject(anItem)

Unfortunately, this doesn't get you the compile-time checking of "items."

Litherum
  • 22,564
  • 3
  • 23
  • 27
2

Swift 5 and Above

let mutableItems = items.mutableCopy() as! NSMutableOrderedSet
mutableItems.add(anItem)
items = mutableItems.copy() as! NSOrderedSet
Saranjith
  • 11,242
  • 5
  • 69
  • 122