Reputation: 27133
I have this delegate method that return for me data from API:
- (void)pagedDataSource:(PagedDataSource *)dataSource
didLoadAdditionalItems:(NSInteger)items; {
NSMutableArray *indexPaths = [NSMutableArray arrayWithCapacity:items];
NSInteger numberOfItems = [dataSource numberOfItems];
for (int i = (int)numberOfItems - (int)items; i < numberOfItems; ++i) {
[indexPaths addObject:[NSIndexPath indexPathForRow:i inSection:0]];
}
[UIView setAnimationsEnabled:NO];
[[self tableView] beginUpdates];
[[self tableView] insertRowsAtIndexPaths:indexPaths
withRowAnimation:UITableViewRowAnimationNone];
[[self tableView] endUpdates];
[UIView setAnimationsEnabled:YES];
}
So first time it works good but when I try to load new entries and then program invokes this delegate method again, it causes a crash.
Let me simple describe how it works.
So I have PagedDataSource object with I initialize with some block that should request data in return when PagedDataSource received data from API it push up data to my view controller with self pointer. So you can see this method above. Then in this method I try to insert needed rows that I just receive. When I scroll table down it request new items and I insert one more rows each time when app invokes this method after receive new data.
So for example if I receive 16 items first time so then I insert rows from 0 to 15
Then when I scroll down table I insert new rows from 16 to 31. So let's say that my limit = 16 items per request.
But the problem that after I load some item for example 144 items, I want to reload my table with new data set. So I starting load data from 0.
Let's say that first time I requested 144 videos then I tap a button and right now I want to see 7 videos from another category in this table. But it cause this crash, because here
- (void)pagedDataSource:(PagedDataSource *)dataSource
didLoadAdditionalItems:(NSInteger)items;
it tries to insert new items from 0 and I got this issue:
*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'attempt to insert row 144 into section 0, but there are only 0 rows in section 0 after the update'
So I checked count for indexPaths array, and here is just 7 items first time.
What should I do? How I can remove or free table view?
So just skip all write before. So let's suppose I load 16 items first time
this is log of indexPaths array I described above:
<__NSArrayM 0x7fbdc1e8af50>(
<NSIndexPath: 0xc000000000000016> {length = 2, path = 0 - 0},
<NSIndexPath: 0xc000000000008016> {length = 2, path = 0 - 1},
<NSIndexPath: 0xc000000000010016> {length = 2, path = 0 - 2},
<NSIndexPath: 0xc000000000018016> {length = 2, path = 0 - 3},
<NSIndexPath: 0xc000000000020016> {length = 2, path = 0 - 4},
<NSIndexPath: 0xc000000000028016> {length = 2, path = 0 - 5},
<NSIndexPath: 0xc000000000030016> {length = 2, path = 0 - 6},
<NSIndexPath: 0xc000000000038016> {length = 2, path = 0 - 7},
<NSIndexPath: 0xc000000000040016> {length = 2, path = 0 - 8},
<NSIndexPath: 0xc000000000048016> {length = 2, path = 0 - 9},
<NSIndexPath: 0xc000000000050016> {length = 2, path = 0 - 10},
<NSIndexPath: 0xc000000000058016> {length = 2, path = 0 - 11},
<NSIndexPath: 0xc000000000060016> {length = 2, path = 0 - 12},
<NSIndexPath: 0xc000000000068016> {length = 2, path = 0 - 13},
<NSIndexPath: 0xc000000000070016> {length = 2, path = 0 - 14},
<NSIndexPath: 0xc000000000078016> {length = 2, path = 0 - 15}
)
then I have switcher that load in the same table another objects and then call the method I described above here is a log of indexPaths (second time):
<__NSArrayM 0x7fbdc1e13920>(
<NSIndexPath: 0xc000000000000016> {length = 2, path = 0 - 0},
<NSIndexPath: 0xc000000000008016> {length = 2, path = 0 - 1},
<NSIndexPath: 0xc000000000010016> {length = 2, path = 0 - 2},
<NSIndexPath: 0xc000000000018016> {length = 2, path = 0 - 3},
<NSIndexPath: 0xc000000000020016> {length = 2, path = 0 - 4},
<NSIndexPath: 0xc000000000028016> {length = 2, path = 0 - 5},
<NSIndexPath: 0xc000000000030016> {length = 2, path = 0 - 6}
)
I got SIGABRT on [[self tableView] endUpdates];
line
Upvotes: 1
Views: 2812
Reputation: 4550
I think you error is when appending the NSIndexPath
specifically in indexPathForRow:i
. And make sure that your dataSource
is updated.
Try this:
[dataSource addObject:@"boom0"];
[dataSource addObject:@"boom1"];
[dataSource addObject:@"boom3"];
[dataSource addObject:@"boom4"];
NSInteger item = 4;
NSMutableArray *indexPaths = [NSMutableArray arrayWithCapacity:item];
for (int i = item; i != 0; i--)
{
[indexPaths addObject:[NSIndexPath indexPathForRow:dataSource.count - i inSection:0]];
}
[tableView beginUpdates];
[tableView insertRowsAtIndexPaths:indexPaths
withRowAnimation:UITableViewRowAnimationNone];
[tableView endUpdates];
EDIT
To repopulate the table what you need to do is to removeAll the object from you dataSource like:
[dataSource removeAllObjects];
the reload your table
[tableView reloadData];
the trick is all in your dataSource
it is up to you how to manipulate it.
//This is using method
- (void)pagedDataSource:(PagedDataSource *)dataSource didLoadAdditionalItems:(NSInteger)items repopulate:(BOOL)repopulate
{
if(repopulate)
{
[dataSource removeAllObjects];
[tableView reloadData];
}
//this will execute the codes below
...
}
You can also track the number of rows in section:
If the current count of dataSource
is less than the previous count
trigger the removeAllObjects
& reloadData
:
int previousCount = 0;
- (void)pagedDataSource:(PagedDataSource *)dataSource didLoadAdditionalItems:(NSInteger)items
{
if([dataSource numberOfItems] < previousCount)
{
[dataSource removeAllObjects];
[tableView reloadData];
}
//this will execute the codes below
...
}
Another option is to just reload the table while the dataSource
was already update, since the cell was already made we don't need to create a new one, or perhaps you like to remake cells? hmm..
- (void)pagedDataSource:(PagedDataSource *)dataSource didLoadAdditionalItems:(NSInteger)items
{
if([dataSource numberOfItems] < previousCount) // || if(repopulate)
{
[tableView reloadData];
return;
}
//this will not / must not execute the codes below
...
}
Hope this helps you, Cheers.. :)
Upvotes: 1