iOS 8: TableView Scroll to RowIndex is not working - uitableview

using this line of code in viewDidLoad after my table get reloaded.
[self.tableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0] atScrollPosition:UITableViewScrollPositionTop animated:NO];
Unfortunately, it's not working for me.
throwing Exception:
Terminating app due to uncaught exception 'NSRangeException', reason: '-[UITableView _contentOffsetForScrollingToRowAtIndexPath:atScrollPosition:]: row (0) beyond bounds (0) for section (0).
i want to hide header section of tableView on application start.
header section contain searchBar. so i want it to be hidden when app start.
i searched really hard but couldn't find the exact answer to my problem. so as last resort, i had to type it myself.
Regards,
A Naive iOS Developer.

This happens when a section has no rows. In this case use NSNotFound. You can find this in UITableView Class Reference.
Obj-C
NSIndexPath *scrollIndexPath = [NSIndexPath indexPathForRow:NSNotFound inSection:0];
[self.tableView scrollToRowAtIndexPath:scrollIndexPath atScrollPosition:UITableViewScrollPositionTop animated:NO];
Swift
let scrollIndexPath = NSIndexPath(forRow: NSNotFound, inSection: 0)
tableView.scrollToRowAtIndexPath(scrollIndexPath, atScrollPosition: .Top, animated: true)

Related

tableview refresh crush Thread1:signal SIGABRT

My app is a IM application, when the application into the background and once again back to the foreground will crush.
This is my part of the code。
-(void)uiAddChatroomMessages:(NSArray*)messages{
NSMutableArray *indexPaths = [[NSMutableArray alloc]init];
int i = (short)self.messageArray.count ;
for (RTIMMessage *msg in messages) {
[self.messageArray addObject:msg];
}
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:i inSection:0];
[indexPaths addObject:indexPath];
[self.chatMessageTableView beginUpdates];
[self.chatMessageTableView insertRowsAtIndexPaths:indexPaths withRowAnimation:UITableViewRowAnimationFade];
[self.chatMessageTableView endUpdates];
[self.chatMessageTableView reloadData];
}
Run to this code "[self.chatMessageTableView endUpdates]",It crush and prompt "Thread1:signal SIGABRT".
2016-08-24 15:49:18.500 RTIM_iOS_Demo[1834:1326398] * Assertion
failure in -[UITableView _endCellAnimationsWithContext:],
/BuildRoot/Library/Caches/com.apple.xbs/Sources/UIKit/UIKit-3512.60.12/UITableView.m:1716
2016-08-24 15:49:18.590 RTIM_iOS_Demo[1834:1326398] * Terminating
app due to uncaught exception 'NSInternalInconsistencyException',
reason: 'Invalid update: invalid number of rows in section 0. The
number of rows contained in an existing section after the update (62)
must be equal to the number of rows contained in that section before
the update (57), plus or minus the number of rows inserted or deleted
from that section (1 inserted, 0 deleted) and plus or minus the number
of rows moved into or out of that section (0 moved in, 0 moved out).'
*** First throw call stack: (0x18238adb0 0x1819eff80 0x18238ac80 0x182d10154 0x1876e1808 0x100072ccc 0x1000728b0 0x100095244
0x10009468c 0x100077d20 0x100241a7c 0x100241a3c 0x1002474e4
0x182340d50 0x18233ebb8 0x182268c50 0x183b50088 0x187552088
0x1000a5340 0x181e068b8) libc++abi.dylib: terminating with uncaught
exception of type NSException
In your method you added to self.messageArray some new objects but added just one row. Modify your code to.
-(void)uiAddChatroomMessages:(NSArray*)messages{
NSMutableArray *indexPaths = [NSMutableArray array];
NSUInteger i = self.messageArray.count;
for (RTIMMessage *msg in messages) {
[self.messageArray addObject:msg];
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:i inSection:0];
[indexPaths addObject:indexPath];
i ++;
}
[self.chatMessageTableView beginUpdates];
[self.chatMessageTableView insertRowsAtIndexPaths:indexPaths withRowAnimation:UITableViewRowAnimationFade];
[self.chatMessageTableView endUpdates];
[self.chatMessageTableView reloadData];
}
As per the stack trace it seems like your index path is wrong. You are using array count as row index, try with (array count-1), hope it will work.
After inserting you the number returned by numberOfRowsInSection must match with the new expected value. You might be returning a constant or a number of elements of an array which hasn't changed.

How to get last cell index path in iOS?

I am building an IOS application where I am using tableView. Now when I reached to last cell I load +10 data from localDB.
After fetching the data I reloaded the tableView that I don't need in place of reload I want to used updated tableView. for that SOF suggested me below code.
[[self tableView] beginUpdates];
[[self tableView] reloadRowsAtIndexPaths:____ withRowAnimation:UITableViewRowAnimationAutomatic];
[[self tableView] endUpdates];
I don't what should be there in reloadRowsAtIndexPaths value. Please can some help me in understanding this above line of code.
You can get the indexPath of the last row in last section like this.
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:(numberOfRowsInLastSection - 1) inSection:(numberOfSections - 1)];
Here, numberOfSections is the value you return from numberOfSectionsInTableView: method. And, numberOfRowsInLastSection is the value you return from numberOfRowsInSection: method for the last section in the table view.
You don't need to reload cells, because there are no cells after your 10th cell. You want your users to see more cells when they get to the last one as in a news app. The solution is to inset more rows below, here is how:
1- create the rows you want to insert
NSMutableArray *newRows = #[[NSIndexPath indexPathForRow:10 inSection:0]];
3- update your data source array
2- [self.tableView insertRowsAtIndexPaths: newRows, UITableViewRowAnimationAutomatic];

Collection view crash on reloadItemsAtIndexPaths

I have an uitableview with a collection view nested inside. Both the Collectionview and the Tableview have just 1 section. In the collectionview cells there are uiimageviews. I'm downloading pictures from a server, and when the picture is downloaded, I'd like to display them in the image view. I'm calling reloadItemsAtIndexPaths to reload the content of the cell to display the picture. This is what i found out so far:
if i'm using
[NSIndexPath indexPathWithIndex:[secondArray indexOfObject:dictionaryToRefresh]]
as the index to refresh in reloadItemsAtIndexPaths, then the first picture loads just fine in the first cell of the collection view. The reloadItemsAtIndexPaths does a nice fade-in effect too. Then it crashes badly with the error:
Assertion failure in -[UICollectionView
_endItemAnimationsWithInvalidationContext:tentativelyForReordering:], /SourceCache/UIKit/UIKit-3347.44/UICollectionView.m:3835 2015-05-03
18:47:02.385 FBomb[3117:798045] *** Terminating app due to
uncaught exception 'NSInternalInconsistencyException', reason:
'attempt to delete section 1, but there are only 1 sections before the
update'
if I use
[NSIndexPath indexPathForItem:[secondArray indexOfObject:dictionaryToRefresh] inSection:0];
All the pictures load just fine! But there is no fade-in effect, which is what i'm trying to achieve. Any ideas as to I can overcome this issue? I'd like to display the pictures with the fade in effect (I really can't understand why it doesn't happens)
Thanks in advance and pardon typos!
EDIT1
Full code:
-(void) reloadItemWithDictionary:(NSDictionary*)dictionaryToRefresh{
BOOL dictionaryFound = FALSE;
NSIndexPath *= [[NSIndexPath alloc]init];
NSIndexPath *indexPathSecondArray = [[NSIndexPath alloc] initWithIndex:0];
for (NSDictionary *firstDictionary in megaArray)
{
NSArray *secondArray = [firstDictionary objectForKey:#"subArray"];
if ([secondArray containsObject:dictionaryToRefresh]){
indexPathFirstArray = [NSIndexPath indexPathForRow:[megaArray firstDictionary] inSection:0];
//THIS FADES THE FIRST ITEM ONLY, THEN CREASHES
//indexPathSecondArray = [NSIndexPath indexPathWithIndex:[secondoArray indexOfObject:dictionaryToRefresh]];
//THESE WORKS, BUT THEY DON'T FADE
indexPathSecondArray = [NSIndexPath indexPathForItem:[secondoArray indexOfObject:dictionaryToRefresh] inSection:0];
//indexPathSecondArray = [NSIndexPath indexPathForRow:[secondoArray indexOfObject:dictionaryToRefresh] inSection:0];
dictionaryFound = TRUE;
break;
}
}
if ( dictionaryFound == TRUE){
dispatch_sync(dispatch_get_main_queue(), ^{
UITableViewCell *tableCell = [tableWithCollectionView cellForRowAtIndexPath:indexPathFirstArray];
UICollectionView *collectionViewInTableCell = (UICollectionView *)[tableCell viewWithTag:1000];
[collectionViewInTableCell performBatchUpdates:^{
[collectionView reloadItemsAtIndexPaths:#[indexPathSecondArray]];
} completion:^(BOOL finished){
}];
});
}
}
What happens when you try this instead:
NSUInteger x[] = {[secondArray indexOfObject:dictionaryToRefresh] , 0};
//I don't know if the first element is section or item. try both.
//NSUInteger x[] = {0, [secondArray indexOfObject:dictionaryToRefresh]};
NSIndexPath *path = [[NSIndexPath alloc] initWithIndexes: x length: 2];
[collectionView reloadItemsAtIndexPaths:[NSArray arrayWithObject:path]];
indexPathWithIndex creates an instance by just using one NSInteger whereas UITableView and UICollectionView requires two values for item/row and section

UITableView selecting row programmatically not having expected effect

I have a tableview with (say) five rows in the only section. The code to edit a custom cell all works, but the problem occurs when I need to reload the table data with new data that has fewer rows, say two. The programme crashes if I have been editing a row that has a higher index than the maximum number of rows in the reloaded table. The exception shows that it is trying to access the higher numbered element beyond the limit of the new table number of rows.
I have tried putting:
[self.tableView selectRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0] animated:YES scrollPosition:UITableViewScrollPositionTop];
in just before the
[self.tableView reloadData];
but it doesn't work.
It can only mean that you are accessing the first row here:
[self.tableView selectRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0] animated:YES scrollPosition:UITableViewScrollPositionTop];
when you do not have the first row.
When you are reloading the tableview, make sure you have atleast one row.
Try doing this:
if([self.tableview numberOfRowsInSection:0]>0)
[self.tableView selectRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0] animated:YES scrollPosition:UITableViewScrollPositionTop];
I believe you used the code below to unselect your cell
[self.tableView selectRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0] animated:YES scrollPosition:UITableViewScrollPositionTop];
If so you should use this instead
NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
[self.tableView deselectRowAtIndexPath:indexPath animated:NO];
In the end, deselecting the old row (i.e. whilst the old data source was still current) and then selecting the first row with the new data source fixed the problem.

NSMutableRLEArray objectAtIndex:effectiveRange:: Out of bounds in populating UITableView

I am using the following code in my application.
NSIndexPath* ipath = [NSIndexPath indexPathForRow:[sectionInfo numberOfObjects]-1 inSection:section];
NSLog(#"ipath %#",ipath);
[self.myTableView scrollToRowAtIndexPath:ipath atScrollPosition: UITableViewScrollPositionTop animated:NO];
And getting the log like this
ipath {length = 2, path = 1 - 9}
But the application crashes with getting the error like
Terminating app due to uncaught exception 'NSRangeException', reason: 'NSMutableRLEArray objectAtIndex:effectiveRange:: Out of bounds'
but if I run the project after commenting like
//[self.myTableView scrollToRowAtIndexPath:ipath atScrollPosition: UITableViewScrollPositionTop animated:NO];
it works fine.I am using fetchedresultcontroller for populating table view and object at indexpath is not null.Any help will be appreciable?
Use this code it may help you
UITableViewCell *cell = (UITableViewCell *)[yourTableName cellForRowAtIndexPath:indexPath];
[yourTableName setContentOffset:CGPointMake(cell.frame.origin.x, cell.frame.origin.y) animated:NO];

Resources