tags:

views:

184

answers:

1

I have trouble to add new item to my table view with core data. Here is the brief logic in my codes. In my ViewController class, I have a button to trigle the edit mode:

- (void) toggleEditing {
  UITableView *tv = (UITableView *)self.view;
  if (isEdit) // class level flag for editing
  {
    self.newEntity = [NSEntityDescription insertNewObjectForEntityName:@"entity1"
      inManagedObjectContext:managedObjectContext];
    NSArray *insertIndexPaths = [NSArray arrayWithObjects:
      [NSInextPath indexPathForRow:0 inSection:0], nil]; // empty at beginning so hard code numbers here.
    [tv insertRowsAtIndexPaths:insertIndexPaths withRowAnimation:UITableViewRowAnimationFade];
    [self.tableView setEditing:YES animated:YES]; // enable editing mode
  }
  else { ...}
}

In this block of codes, I added a new item to my current managed object context first, and then I added a new row to my tv. I think that both the number of objects in my data source or context and the number of rows in my table view should be 1.

However, I got an exception in the event of tabView:numberOfRowsInSection:

Invalid update: invalid number of rows in section 0. The number of rows contained in an existing section after the update (0) must be equal to the number of rows contained in that section before the update (0), plus or minus the number of rows inserted or deleted from that section (1 inserted, 0 deleted).

The exception was raised right after the delegate event:

- (NSInteger) tableView:(UITableView *) tableView numberOfRawsInSection:(NSInteger) section {
  // fetchedResultsController is class member var NSFetchedResultsController 
  id <NSFechedResultsSectionInfo> sectionInfo = [[fetchedResultsController sections]
    objectAtIndex: section];
  NSInteger rows = [sectionInfo numberOfObjects];
  return rows;
}

In debug mode, I found that the rows was still 0 and the event invoked after the the even of toggleEditing. It looks like that sectionInfo obtained from fetchedResultsController did not include the new entity object inserted. Not sure if I miss anything or steps? I am not sure how it works: to get the fetcedResultsController notified or reflect the change when a new entity is inserted into the current managed object context?

A: 

I think I got a solution. Actually, I don't need to create entity in the toggleEditing event. Then entity object should be created when an insert event is committed. Here is the update of my codes in the toggleEditing event:

- (void) toggleEditing {
  UITableView *tv = (UITableView *)self.view;
  if (isEdit) // class level flag for editing
  {
    insertRows = 1; // NSInteger value defined in the class or header
    NSArray *insertIndexPaths = [NSArray arrayWithObjects:
    [NSInextPath indexPathForRow:0 inSection:0], nil]; // empty at beginning so hard code numbers here.
    [tv insertRowsAtIndexPaths:insertIndexPaths withRowAnimation:UITableViewRowAnimationFade];
    [self.tableView setEditing:YES animated:YES]; // enable editing mode
  }
  else { insertRows = 0; ...}
}

In the event, a row is dynamically inserted into the current table view. Since a new row is added, in the following delegate, I have to make sure the rows returned in the section reflects the incitement:

- (NSInteger) tableView:(UITableView *) tableView numberOfRawsInSection:(NSInteger) section {
  // fetchedResultsController is class member var NSFetchedResultsController 
  id <NSFechedResultsSectionInfo> sectionInfo = [[fetchedResultsController sections]
    objectAtIndex: section];
  NSInteger rows = [sectionInfo numberOfObjects];
  return rows + insertRows;
}

Then in the delegate tableView:numberOfRowsInSection:, I add accessory to the inserted row to mark it as Add.

The lesson I learned from this experience is that when a row is dynamically added to the table view, an entity object is not needed to be created in the managed object context. The object is created only on the event to commit the edit style (add). Another important thing to remember is that I have to track the rows in section in sync with the dynamically inserted or removed rows, as described above.

By the way, the reason I tried to add a row to my table view as an UI to add new entity or data is based on iPhone's Contact application. I understand that the most common way to add new entity is to display Add button on the navigation bar, but Contact app provides an alternative way to do that. If you select one person and touch the edit button on navigation bar, several Add rows are displayed in the table view in an animation way. I am not sure if my solution is the correct way to achieve this goal. Please correct me and I would like to accept any good answers!

David.Chu.ca