NSRangeException when deleting last UICollectionViewCell - ios

I have a UICollectionView with 1 section. The user can delete cells from the collection, and I use this code for removal:
[self.collectionView performBatchUpdates:^{
[self.collectionView deleteItemsAtIndexPaths:#[[NSIndexPath indexPathForItem:i inSection:0]]];
[self.media removeObjectAtIndex:i];
} completion:nil];
This works fine for every cell except for the last cell in the collection, which crashes the app every time with the error: Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[__NSArrayM objectAtIndex:]: index 3 beyond bounds [0 .. 2]
NSZombies aren't showing me a stack trace so I put a breakpoint on every line in my code that accesses an array but none were hit, and I found that this error is thrown after deleteItemsAtIndexPaths, numberOfSectionsInCollectionView and sizeForItemAtIndexPath, but before numberOfItemsInSection and cellForItemAtIndexPath
What could be causing this crash? How can I debug it?
There are some similar SO posts, but this one from 2 years ago has no answer UICollectionView crash when deleting last item, and this one only solves the problem if you want to delete the whole section: Removing the last Cell in UICollectionView makes a Crash
UPDATE, here are the data source delegate methods that run before the crash:
- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView {
return 1;
}
-(CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath {
return CGSizeMake(floorf(screenWidth/3), 200);
}

Just put the Exceptions Breakpoint and you'll find where exactly it is crashing.

Related

beginUpdates endUpdates crash with nothing between

I am entirely confused. I am modifying my table and it's crashing while up via adding/deleting rows and reloading sections. So I stopped adding and deleting rows, and it still crashes. So I stopped reloading sections and it still crashes. So I just put the code:
[self.tableView beginUpdates];
[self.tableView endUpdates];
with this code it crashes, without it's fine.
Why?
2014-09-12 21:52:41.257 weatherApp[12616:60b] * Terminating app due to uncaught exception 'NSRangeException', reason: '* -[__NSArrayM objectAtIndex:]: index 1 beyond bounds [0 .. 0]'
* First throw call stack:
(0x2ea84f83 0x392ffccf 0x2e9bb7cb 0x3149eaef 0x3149cd8f 0x3149c843 0x31474e5b 0xeb82d 0xed059 0x313d48f7 0x3137bc27 0x3137b47d 0x312a1d59 0x30f1f62b 0x30f1ae3b 0x30f1accd 0x30f1a6df 0x30f1a4ef 0x30f6dc49 0x33d3a75d 0x2f770451 0x2ea44ea9 0x2ea4fa67 0x2ea4fa03 0x2ea4e1d7 0x2e9b8ebf 0x2e9b8ca3 0x33912663 0x3130514d 0x107599 0x3980cab7)
libc++abi.dylib: terminating with uncaught exception of type NSException
Edit: Be advised I am calling this update in cellForRowAtIndexPath because I need to check for an update as new cells are displayed. The code that causes this update is the [self updateSection code, which right now only runs begin updates, end updates.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
WFHNotamTableViewCell *cell = (WFHNotamTableViewCell *)[tableView dequeueReusableCellWithIdentifier:CellTableIdentifier forIndexPath:indexPath];
if (!cell)
{
NSLog(#"Dequeue blank cell");
}
NSLog(#"Loading %d - %d", indexPath.section, indexPath.row);
NSString *group;
NSString *icao = [metarManager getIdentifierAtTotalIndex:indexPath.section andReturnGroup:&group];
NSMutableDictionary *notamDict = [notamManager getNotamFor:icao atVisibleIndex:indexPath.row];
NSDate *lastUpdate = [notamDict objectForKey:#"timeDownloaded"];
[self updateSection:indexPath.section andLastUpdate:lastUpdate];
return cell;
Thank you!

UICollectionView crash when deleting last item

I am trying to update the uicollection view whenever I delete a item. All the cells are deleting fine but if I delete the last cell in that collection view App crashes and I have put
[self.collectionview performBatchUpdates:^{
[postarray removeObjectAtIndex:indexPath.item];
[self.collectionview deleteItemsAtIndexPaths:#[[NSIndexPath indexPathForRow:indexPath.row inSection:1]]];
} completion:^(BOOL finished) {}];
The error I got is 'NSRangeException', reason: '* -[__NSArrayI objectAtIndex:]: index 17 beyond bounds [0 .. 16]' . Even array and collection view item starts at same index,I got this message
I was getting the same error message with the same lines of code, and it turned out it had nothing to do with the UICollectionView data source, but with a parallel array in another part of the app that updated its contents after but not its active index after the delete.
To find errors like this, enable Exception breakpoints: NSRangeException when deleting last UICollectionViewCell
Just inverse your two lines. You need to remove cell before to remove your object.
[self.collectionview performBatchUpdates:^{
[self.collectionview deleteItemsAtIndexPaths:#[[NSIndexPath indexPathForRow:indexPath.row inSection:1]]];
[postarray removeObjectAtIndex:indexPath.item];
} completion:^(BOOL finished) {}];

UITableView and UICollectionView interaction ios?

Please can anyone help me to achieve something like this-
(developing for iPad iOS7) In UIViewController i have UITableView & UICollectionView(like splitViewController).I just want to change image in UICollectionView when i tap on UITableViewCell.(I am using button over tableViewCell and collecting index in NSInteger).
Please help me to achieve this,I am trying from so many days,but can't achieve till now. :(
Here is the code what i have done till now.
In my viewDidLoad:
self.collectionViewImages=[[NSMutableArray alloc]initWithObjects:#"1.jpg",#"2.jpg",#"3.jpg",nil] ;
Then in CollectionViewMethods:
-(NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView
{
return 1;
}
-(NSInteger)collectionView:(UICollectionView *)collectionView
numberOfItemsInSection:(NSInteger)section
{
return [_collectionViewImages count];
}
-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView
cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
UICollectionViewCell *myCell = [collectionView dequeueReusableCellWithReuseIdentifier:#"Cell"
forIndexPath:indexPath];
NSString *collectionViewImageName=[self.collectionViewImages objectAtIndex:indexPath.row];
UIImageView * collectionImage = (UIImageView*)[myCell viewWithTag:11];
collectionImage.image =[UIImage imageNamed:collectionViewImageName];
return myCell;
}
Then on ButtonClick(ofTableViewCell)--
(i am collecting tag of each button in NSInteger and using that property in numberOfItemsInSection like this,
-(void)btnTapped:(id)sender{
int tag= [(UIButton *)sender tag];
NSLog(#"Button Pressed%d",tag);
_buttonIndex=tag;
//_buttonIndex is NSInteger property
//If i add object in NSMutableArray and call reloadData my UI hangs here only.
//If I empty my NSMutableArray and add new objects in it and then call reloadData, I am getting NSRangeException.
}
And now i am using this property in numberOfItemsInSection as...
if (_buttonIndex==1){
[collectionImage setImage:[UIImage imageNamed:[_array1 objectAtIndex:indexPath.row]]];
//My _array1 has 4 objects and my collectionViewImages array has 7 objects.
}
i am getting error message as
*** Terminating app due to uncaught exception 'NSRangeException',
reason: '*** -[__NSArrayM objectAtIndex:]: index 4 beyond bounds [0 .. 3]'
Its crashing because you are trying to get an item from the array at index 4. But there are only indexes: 0,1,2,3.
Double check the contents of array1 on line (if it crashes here):
[collectionImage setImage:[UIImage imageNamed:[_array1 objectAtIndex:indexPath.row]]];
Otherwise find the other place where you call objectAtIndexand check if it crashes there.

UICollectionView insertSections error - NSInvalidArgumentException reason setObjectForKey object cannot be nil UICollectionViewItemKey

I'm getting an error using a UICollectionView as follows:
2013-11-29 17:29:07.832 Clients[34200:70b]
*** Terminating app due to uncaught exception 'NSInvalidArgumentException',
reason: '*** setObjectForKey: object cannot be nil
(key: <_UICollectionViewItemKey: 0x8da14f0>
Type = DV ReuseID = (null) IndexPath = (null))'
And the code is as follows, where I essentially have two NSMutableArrays -- one containing all entries and the other used to reduce the entries to one section -- in this bit, I'm adding all the missing sections back in (hope that makes sense).
[self.collectionView performBatchUpdates:^{
NSString *selectedMarketSector = [[[[_marketSectors objectAtIndex:0] clients] objectAtIndex:0] clientMarketSector];
NSMutableIndexSet *insertSections = [[NSMutableIndexSet alloc] init];
for (TBMarketSector* sector in _allMarketSectors) {
if (![[[[sector clients] objectAtIndex:0] clientMarketSector ] isEqualToString:selectedMarketSector]) {
[insertSections addIndex:[_allMarketSectors indexOfObject:sector]];
}
}
_marketSectors = [self.allMarketSectors mutableCopy];
[self.collectionView insertSections:insertSections];
} completion:^(BOOL finished) {
[self setLayoutStyle:TBLayoutStacks animated:YES];
}];
The line that 'appears' to be causing the problem is the [self.collectionView insertSections:insertSections]; but I'm wondering if there is something weird going on elsewhere...
Thanks for any assistance you can provide.
Believe it or not, it seems this particular issue is actually relating to a UICollectionElementKindSectionFooter that I don't want.
I should have mentioned that this only started being a problem with iOS7 (not the first problem I've had with Collection Views after switching to iOS 7 either).
Anyway, my custom UICollectionViewFlowLayout implemented the - (UICollectionViewLayoutAttributes *)layoutAttributesForSupplementaryViewOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath method and was returning some attributes for all supplementary views.
To fix this particular problem, I needed to add the following:
if ([kind isKindOfClass:[UICollectionElementKindSectionFooter class]])
return nil;
Thanks.
This kind of crash can be if in method
func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView
You try to get in dequeueReusableSupplementaryView(ofKind: - view of type elementKindSectionHeader, when kind is elementKindSectionFooter.
Check is nib register for current kind.
Thanks.

UICollectionView deleteItemsAtIndexPaths failure

- (void)deleteCell
{
[self.collectionViewMenu performBatchUpdates:^{
[self.itemsArray removeObjectAtIndex:1];
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:1 inSection:0];
[self.collectionViewMenu deleteItemsAtIndexPaths:#[indexPath]];
} completion:^(BOOL finished) { }];
}
Please help to solve this problem, what am I doing wrong? I got this error after trying to delete an item in my collectionView.
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** setObjectForKey: object cannot be nil (key: <_UICollectionViewItemKey: 0x8d705e0> Type = SV Kind = UICollectionElementKindSectionHeader IndexPath = <NSIndexPath: 0x8d6f4b0> {length = 2, path = 0 - 0})'
I solve the problem with remove the header and footer size delegates. the problem was in the fact that I do not return a header or footer.
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout referenceSizeForHeaderInSection:(NSInteger)section;
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout referenceSizeForFooterInSection:(NSInteger)section;
setObjectForKey: object cannot be nil means that the cell you are trying to delete is possibly already been deleted.
You should try to debug it and see when you call the delete what views at what index paths are actually in your collection view.
You probably need to implement:
- (UICollectionReusableView *)collectionView:(UICollectionView *)collectionView viewForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath;
in your dataSource. This did the trick for me.
I just try to call collectionViewLayout.invalidateLayout() before performBatchUpdates. Then make sure the layout implementation are correctly and make sure that you are not returning negative height for cell. For more detail you can visit below GitHub link.
https://github.com/ra1028/DifferenceKit/issues/13
It helped me to fix the error.

Resources