UICollectionView Scrolling to an Item - ios

I am trying to memorize an index for an item (indexPath.item) in a UICollectionView and at a later time, after the view is replaced and then restored, to scroll to that memorized item.
When memorizing the item, indexPath, and indexPath.item are:
indexPath is: <NSIndexPath 0x1d87b380> 2 indexes [0, 32]
indexPath.item is: 32
When recalculating the indexPath later for that item, indexPath, and indexPath.item are:
indexPath is: <NSIndexPath 0x1d8877b0> 2 indexes [0, 32]
item is: 32
I try to scroll to the memorized location by using:
NSIndexPath *iPath = [NSIndexPath indexPathForItem:i inSection:0];
[self collectionView scrollToItemAtIndexPath:iPath atScrollPosition:UICollectionViewScrollPositionCenteredVertically animated:NO];
I receive an error:
attempt to scroll to invalid index path

Do you call [self.collectionView reloadData];
before trying to scroll to the indexPath?
If you want to relocate the indexPath when the reloadData finishes, place the code in a block like this:
[UIView animateWithDuration:0
animations: ^{ [self.collectionView reloadData]; }
completion:^(BOOL finished) {
NSIndexPath *iPath = [NSIndexPath indexPathForItem:i inSection:0];
[self collectionView scrollToItemAtIndexPath:iPath atScrollPosition:UICollectionViewScrollPositionCenteredVertically animated:NO];
}];
Before calling scrollToItemAtIndexPath, you could also check the number of items in section to make sure i is valid, or you still will get the same error.

Printing numberofItemsInSection revealed that the view it used for scrolling was stale. When I used the scrollToItemAtIndexPath after refreshing the view, it worked!

Related

Load more to last position in UITableView

I try to Build UITableView That load every time a 5 object and when I notice that the scroll table in the last position I reload table data and this open the table from the top again.
how I can save the position and when table reload back to last cell I see ?
Use the below code before you reload the table data
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:(numberOfRowsInLastSection - 1) inSection:(numberOfSections - 1)];
By the above line you will get the position of last row of table.
Use this code after reloading the tableView
[tableView scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionTop animated:YES];
This will scroll to already saved position.
I find a solution in this post - UITableView , Scroll to bottom on reload?
[postTableView reloadData];
NSIndexPath* ipath = [NSIndexPath indexPathForRow: oldSkip -1 inSection: 1];
[postTableView scrollToRowAtIndexPath: ipath atScrollPosition: UITableViewScrollPositionTop animated:YES];

iOS UITableView Scroll to bottom of section

I am going to make a tableview with 2 sections inside it. I can add cells to every section programmatically and when i add, i scroll to the end of tableview using
[_tableView setContentOffset:CGPointMake(0, CGFLOAT_MAX)];
My question is how can i scroll to the end of the section 0, so that when user add a cell to section 0, tableview scroll dynamically to the last cell in section 0.
thanks.
You can try with this code:
int yourSection = 2;
int lastRow = [tableView numberOfRowsInSection:yourSection] - 1;
[tableView scrollToRowAtIndexPath:[NSIndexPath lastRow inSection:yourSection] atScrollPosition:UITableViewScrollPositionBottom animated:YES];
You get the numbers of rows in your section, then scroll to that indexPath.
All the suggestions above are correct, at least based on the docs. But it did not work in my case - I could not get the scroll to show the last row in the table view. I had to add a delay in scrolling to make that work.
- (void)scrollToTheBottom:(BOOL)animated
{
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:rowCount-1 inSection:0];
[self.tableView scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionBottom animated:animated];
}
I called the above as:
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[self scrollToTheBottom:YES];
});
when you inserting row at end you have its index path, you can use scrollToIndexPath method of tableview to scroll
[self.liveChannelsTable scrollToRowAtIndexPath:IndexPath atScrollPosition:UITableViewScrollPositionTop animated:YES];
Just in case, this is solution in Swift:
extension UITableView {
func scrollToBottom(animated: Bool = true) {
let sections = self.numberOfSections
let rows = self.numberOfRowsInSection(sections - 1)
self.scrollToRowAtIndexPath(NSIndexPath(forRow: rows - 1, inSection: sections - 1), atScrollPosition: .Bottom, animated: true)
}
}
In Swift 3 it's been updated to:
let indexPath = IndexPath(row: self.numberOfRowsInSection(0) - 1), section: 0)
self.commentsTableView.scrollToRow(at: indexPath, at: .bottom, animated: false)

How to go to the first cell in UITableView after reloading data

Currently when I reload the data in the table it stays in the same scroll position:
[self.tableView reloadData];
How can I get the scroll position/height to go back to the top/the first cell?
You can use the following method to scroll to any index path in your table view:
[self.tableView scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionTop animated:YES];
So, for the first cell, your indexPath would be:
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:0 inSection:0];
You can change the scrollPosition and animated parameters to get your desired effect/result.
Swift 4 version
let indexPath = IndexPath(row: 0, section: 0)
tableView.scrollToRow(at: indexPath, at: .top, animated: false)
I got this crash because I was trying to scroll to row 0 section 0 of an empty tableView. Make sure your tableData.count > 0 before you execute the scrollToRow().

After Inserting some rows in UITableView, it is not scrolling in ios 7

Hi I have created UITableView. On Touch of it cell, i am inserting more rows in it. After inserting more rows in UITableView, scroll is not working. This is only happening in ios 7.
Have any one came across this problem??
here is the code of insertion.
NSArray *rowIndex = [NSArray arrayWithObject:[NSIndexPath indexPathForRow:1 inSection:[self.lastSelectedIndex section]]];
[self.table beginUpdates];
[self.table insertRowsAtIndexPaths:rowIndex withRowAnimation:UITableViewRowAnimationNone];
[self.table endUpdates];
i am not sure what does going on your code but if you want to scroll after every add row just call the method bellow (note :- modify the code as per your variable name)
-(void)goToBottom
{
NSInteger lastSectionIndex = MAX(0, [myTableName numberOfSections] - 1);
NSInteger lastRowIndex = MAX(0, [ myTableName numberOfRowsInSection:lastSectionIndex] - 1);
NSIndexPath *lastIndexPath = [NSIndexPath indexPathForRow:lastRowIndex inSection:lastSectionIndex];
if([myArray count] > 0)
{
[myTableName scrollToRowAtIndexPath:lastIndexPath atScrollPosition:UITableViewScrollPositionBottom animated:YES];
}
}
Have you created the View with the storyboard? maybe you have to check your constraints.
if your table view occupies all of the space in the view, select it then go to "Editor>pin>top space to superview and bottom space to superview"

UITableView inserting section at top while scrolling

I am inserting new section (section contains 3 cells) top of UITableView while SCROLLING TOP.
[_mainTable beginUpdates];
[_mainTable insertSections:[NSIndexSet indexSetWithIndex:0] withRowAnimation:UITableViewRowAnimationNone];
[_mainTable endUpdates];
Section gets inserting properly. But it takes me top of Table i.e. cell 0 or row 0. I want this transaction to be smooth. I can insert
[_mainTable scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:1 inSection:1] atScrollPosition:UITableViewScrollPositionBottom animated:NO];
after endUpdates but it shows quick jerk because it takes you top of Table then suddenly scroll it to your last position.
How can i make it smooth.
Thanks
I haven't done exhaustive testing on this, but this seems promising:
Identify NSIndexPath of one of the visible cells.
Get its rectForRowAtIndexPath.
Get the current contentOffset of the table, itself.
Add the section, but call reloadData instead of insertSections (which prevents jarring scrolling).
Get the updated rectForRowAtIndexPath that you got in step 2.
Update contentOffset by the difference of the result from step 5 and that of step 2.
Thus:
[self.sections insertObject:newSection atIndex:0]; // this is my model backing my table
NSIndexPath *oldIndexPath = self.tableView.indexPathsForVisibleRows[0]; // 1
CGRect before = [self.tableView rectForRowAtIndexPath:oldIndexPath]; // 2
CGPoint contentOffset = [self.tableView contentOffset]; // 3
[self.tableView reloadData]; // 4
NSIndexPath *newIndexPath = [NSIndexPath indexPathForRow:oldIndexPath.row inSection:oldIndexPath.section + 1];
CGRect after = [self.tableView rectForRowAtIndexPath:newIndexPath]; // 5
contentOffset.y += (after.origin.y - before.origin.y);
self.tableView.contentOffset = contentOffset; // 6

Resources