I have a UITableView that sometimes has rapid insertions of new rows. The insertion of the new rows is handled by a notification observer listening for the update notification fired whenever the underlying data changes. I use a @synchronized block around all the data model changes and the actual notification post itself... hoping that each incremental data change (and row insertion) will be handled separately. However, there are times when this still fails. The exception will tell me that it expects 10 rows (based on the count from the data model), it previously had 8 rows, but the update notification only told it to insert a single row (as this is the first of two rapidly fired notifications).
I'm trying to understand how other people tend to handle these types of situations. How do other developers mitigate the problems of having multi-threaded race conditions between two table view update operations? Should I have a more secure lock that controls the update notifications (and why isn't @synchronized doing what it's supposed to)?
Any advice is greatly appreciated! Thanks.
Some pseudo-code:
My model class has a method like this, which gets called by other threads to append new rows to the table view:
- (void)addRow:(NSString *)data
{
@synchronized(self.arrayOfData)
{
NSInteger nextIndex = self.arrayData.count;
[self.arrayData addObject:data];
[NSNotificationCenter.defaultCenter postNotificationName:kDataUpdatedNotification object:self userInfo:@{@"insert": @[[NSIndexPath indexPathForRow:nextIndex inSection:0]]}];
}
}
My controller class has a method like this to accept the kDataUpdatedNotification notification and actually perform the row insertion:
- (void)onDataUpdatedNotification:(NSNotification *)notification
{
NSDictionary *changes = notification.userInfo;
[self.tableView insertRowsAtIndexPaths:changes[@"insert"] withRowAnimation:UITableViewRowAnimationBottom];
}