insertItemsAtIndexPaths Update Error
I see several things wrong here. First, I'm not sure why you're using dispatch_sync, I don't have much experience with GCD, and I couldn't make it work with that in there (it seemed to hang, and the UI was unresponsive). Perhaps someone else can help with that. Second, in the loop where you add index paths, you're looping over resultsSize, which as I understand it, is the size of the array before the update, which is not what you want -- you want to start the new indexes at resultsSize and loop up to resultsSize + newData.count. Lastly, when you call insertItemsAtIndexPaths, you want to do that once, not in a loop. I tried this, and it worked to update the collection view (I didn't try it from scratch with an empty collection view):
-(void)addNewCells {
[self.collectionView performBatchUpdates:^{
int resultsSize = [self.results count];
[self.results addObjectsFromArray:newData];
NSMutableArray *arrayWithIndexPaths = [NSMutableArray array];
for (int i = resultsSize; i < resultsSize + newData.count; i++) {
[arrayWithIndexPaths addObject:[NSIndexPath indexPathForRow:i inSection:0]];
}
[self.collectionView insertItemsAtIndexPaths:arrayWithIndexPaths];
}
completion:nil];
}
Related videos on Youtube
darksky
C, C++, Linux, x86, Python Low latency systems Also: iOS (Objective-C, Cocoa Touch), Ruby, Ruby on Rails, Django, Flask, JavaScript, Java, Bash.
Updated on September 15, 2022Comments
-
darksky over 1 year
In UICollectionView, I am trying to use
performBatchUpdates:completion
to perform updates to my grid view. My data source array isself.results
.Here's my code:
dispatch_sync(dispatch_get_main_queue(), ^{ [self.collectionView performBatchUpdates:^{ int resultsSize = [self.results count]; [self.results addObjectsFromArray:newData]; NSMutableArray *arrayWithIndexPaths = [NSMutableArray array]; if (resultsSize == 0) { [arrayWithIndexPaths addObject:[NSIndexPath indexPathForRow:0 inSection:0]]; } else { for (int i = 0; i < resultsSize; i++) { [arrayWithIndexPaths addObject:[NSIndexPath indexPathForRow:resultsSize + i inSection:0]]; } } for (id obj in self.results) [self.collectionView insertItemsAtIndexPaths:arrayWithIndexPaths]; } completion:nil];
Explanation of what I have / what I'm doing:
This code runs fine when the initial insertion into the collection view is done. However, when I add/insert more data into my collection view (by updating
self.results
and calling this), this gives the following error:* Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Invalid update: invalid number of items in section 0. The number of items contained in an existing section after the update (8) must be equal to the number of items contained in that section before the update (4), plus or minus the number of items inserted or deleted from that section (32 inserted, 0 deleted) and plus or minus the number of items moved into or out of that section (0 moved in, 0 moved out).'
I understand this means that the data source wasn't updated properly. However, when querying my
self.results
array, I see the new count of the data. I am doing that on the first line usingaddObjectsFromArray
. I also stored the old results size inresultsSize
. I use that variable to add the newly added index paths intoarrayWithIndexPaths
.Now when adding/inserting items, I tried the following for-loops:
for (id obj in self.results)
which is what I am using now. It works initially but further inserts crashes.for (UIImage *image in newData)
works as well initially but further inserts crash.From the name of the function, I believe that
insertItemsAtIndexPaths
will insert all items at those index paths without a loop. However, without a loop, the app crashes when it initially tries to populate the data.I also tried looping from
resultsSize + 1
until the newself.results
count (which contains the new data) and that also crashes at the initial update.Any suggestions about what I'm doing wrong?
Thank you,
-
darksky over 11 yearsThe dispatch statement is actually executing on the main thread so that should be fine. My mistake for including it. This code though crashes at the initial insertion with the error:
The number of items contained in an existing section after the update (4) must be equal to the number of items contained in that section before the update (0), plus or minus the number of items inserted or deleted from that section (1 inserted, 0 deleted) and plus or minus the number of items moved into or out of that section (0 moved in, 0 moved out).'
-
rdelmar over 11 yearsAs I said, I didn't try this starting rom an empty collection view. In your test is resultsSize = 0? It seems to me that if it is, you should get rid of the if-else clause and just have the else part there -- I think that would then work from an empty array. I've updated my post to show how I think it should work.
-
darksky over 11 yearsGreat! It worked. Thanks a lot. One question however since you seem to have already gotten UICollectionViews working programatically: in landscape mode it does not seem to scroll down when adding new items. How do you handle extending the collection view scroll when new items are added? Would you reset the frame's height every time an item is added? If so, how would you do so to accommodate for both portrait and landscape?
-
rdelmar over 11 yearsI haven't tried rotation yet -- I remember something from the WWDC 2012 about that, I'll have to check it out and get back to you.
-
rdelmar over 11 yearsI'm not sure what you mean by "it doesn't seem to scroll down when adding new items" Are you not getting scrolling in landscape mode, because I am? I haven't added any code to deal with rotation, but it seems to be the default.
-
darksky over 11 yearsActually, I noticed that UICollectionView is reinserting the same images over and over again. What it's doing is initially, it inserts the first four images fine. After that, it inserts images 2-5. Loading more, it shows 3-6 etc... Why is that happening? My arrayForIndexPaths always contains the indices of the new data, and my self.results has the new data appended at the end of its array.
-
rdelmar over 11 yearsI don't know why it would be doing that, mine isn't. Maybe you should edit your post to show what code you're using now (or start a new question with your current code).
-
darksky over 11 yearsI'll start a new quesiton with two new issues. UICollectionView is not well documented for development without storyboard or interface builder its a lot of headache.