Szybkie wstawianie wierszy do UITableView powoduje NSInternalInconsistencyException
Mam UITableView, który czasami ma szybkie wstawianie nowych wierszy. Wstawianie nowych wierszy jest obsługiwane przez obserwatora powiadomień, który nasłuchuje powiadomienia o aktualizacji uruchamianego za każdym razem, gdy zmieniają się podstawowe dane. Używam bloku @synchronizowanego wokół wszystkich zmian modelu danych i samego postu powiadomienia ... mając nadzieję, że każda przyrostowa zmiana danych (i wstawienie wiersza) będzie obsługiwana oddzielnie. Jednak zdarzają się sytuacje, w których nadal się to nie udaje. Wyjątek powie mi, że oczekuje 10 wierszy (w oparciu o liczbę z modelu danych), poprzednio miał 8 wierszy, ale powiadomienie o aktualizacji nakazywało mu wstawić pojedynczy wiersz (ponieważ jest to pierwszy z dwóch szybko zwalnianych powiadomień ).
Próbuję zrozumieć, jak inni ludzie radzą sobie z tego typu sytuacjami. W jaki sposób inni programiści łagodzą problemy związane z wielowątkowymi warunkami wyścigu między dwiema operacjami aktualizacji widoku tabeli? Czy powinienem mieć bardziej bezpieczny blokadę, która kontroluje powiadomienia o aktualizacjach (i dlaczego @synchronizuje, co ma robić)?
Wszelkie porady są bardzo mile widziane! Dzięki.
Niektóre pseudo-kod:
Moja klasa modelu ma taką metodę, która jest wywoływana przez inne wątki w celu dodania nowych wierszy do widoku tabeli:
- (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]]}];
}
}
Moja klasa kontrolera ma taką metodę, aby zaakceptować powiadomienie kDataUpdatedNotification i faktycznie wykonać wstawienie wiersza:
- (void)onDataUpdatedNotification:(NSNotification *)notification
{
NSDictionary *changes = notification.userInfo;
[self.tableView insertRowsAtIndexPaths:changes[@"insert"] withRowAnimation:UITableViewRowAnimationBottom];
}