Question

I have a problem to insertNewObject in an entity being the child in a parent/child relationship. It's a CoreData app with a local SQLite base. There are 2 entities presented with 2 TableViews on the main window. Using contentSet, the table for the child will only show data relating to the selected parent.

Adding data to the child is done by showing a sheet with a table of items coming from a 3rd entity. User must pick from this table then click Add. On dismissing the sheet, the child table on main window should be updated with a new row. Problem: nothing appears.

Checking the database content with a third-party app, I see that the new data is there but it doesn't appear on the table view because no info on the relationship with parent was stored, so it doesn't know to which parent it relates.

My code is missing info about this but I just don't see how I should program this. In other words: on dismissing sheet, identify which parent is selected and specify this relationship info when inserting the new data in the child. I would appreciate any help.

Here is my code:

  // there are 3 entities: Collectors (parent), CollectedItems (child) and Items.

  // we call the sheet presenting the Items list to pick from
  - (IBAction)showAddItemDialog:(id)sender {
    [NSApp beginSheet:addItemDialog
modalForWindow:window
modalDelegate:self
    didEndSelector:@selector(didEndAddItemSheet:returnCode:contextInfo:)
    contextInfo:nil];
  }

  // we dismiss the sheet by clicking on Cancel or Add
  - (IBAction)dismissAddItemDialog:(id)sender {
[NSApp endSheet:addItemDialog returnCode:([sender tag])];
    [addItemDialog orderOut:sender];
  }

  // depending on clicked button, do nothing or pass selected data
  - (void)didEndAddItemSheet:(NSWindow *)sheet returnCode:(int)returnCode contextInfo (void *)contextInfo {
    if (returnCode == 0) {
    // do nothing, this is the effect of clicking on Cancel
    }
    if (returnCode == 1) {
    NSString *theName = [[[itemsPickerController selectedObjects] valueForKey:@"itemName"] objectAtIndex:0];
    // above, we get the value from the itemName attribute sleected in the Items list
    NSLog (@"%@", theName);
    // the variable is displayed in the console, so it was correctly selected
    [self addNewItemWithName:theName];
    }
  }

  // we use the passed data to create new object (row) in the CollectedItems entity
  - (id)addNewItemWithName:(NSString *)theName {
    NSEntityDescription *newContent = [NSEntityDescription insertNewObjectForEntityForName:@"CollectedItems" inManagedObjectContext:[self managedObjectContext]];
    [newContent setValue:theName forKey:@"collectedItemName"];
    // above, we insert a new row in CollectedItems, assigning the value theName to the attribute collectedItemName
    return nil;
  }
Was it helpful?

Solution

You need to add the relationship between your CollectedItems object you created and its parent the Collectors object. Collectors will have a core data utility method on it (if you have generated the core data managed object classes). It will be called something like addCollectedItemsObject.

Reloading the tableViews should then update with the correct data - as it now knows the relationship.

Even better would be to use NSFetchedResultsController to control the data in your tables so that when you update your data model, the tables will automatically reflect the changes.

OTHER TIPS

And for the record, for those it might help, here is the final working code:

Ensuring the method was generated in the corresponding Collectors class file for (core data managed object classes).

// header file
@class Collecteditems;
@interface Collectors : NSManagedObject { }
@property (nonatomic, retain) NSSet* content;
@end
@interface Collectors (CoreDataGeneratedAccessors)
- (void)addContentObject:(Collecteditems *)value;
@end

// implementation file
#import "Collectors.h"
#import "Collecteditems.h"
@implementation Collectors 
@dynamic content;
- (void)addContentObject:(Collecteditems *)value {
NSSet *s = [NSSet setWithObject:value];
[self willChangeValueForKey:@"collecteditems" withSetMutation:NSKeyValueUnionSetMutation usingObjects:s];
[[self primitiveValueForKey:@"collecteditems"] addObject:value];
[self didChangeValueForKey:@"collecteditems" withSetMutation:NSKeyValueMinusSetMutation usingObjects:s];
}

Then adding the addObject method on the NSArrayController controlling the collected items table (see id in original post for reference).

- (id)addNewItemWithName:(NSString *)theName {
    NSEntityDescription *newContent = [NSEntityDescription insertNewObjectForEntityForName:@"CollectedItems" inManagedObjectContext:[self managedObjectContext]];
    [newContent setValue:theName forKey:@"collectedItemName"];
    [collectedItemsController addObject:newContent]; // line added
    return nil;
  }
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top