selectRowAtIndexPath: animated: scrollPosition: - Row is "selected" - objective-c

I am using the following code to scroll to the top of a tableView:
NSIndexPath *topIndexPath = [NSIndexPath indexPathForRow:0 inSection:0];
[self.listTableView selectRowAtIndexPath:topIndexPath animated:NO scrollPosition:UITableViewScrollPositionMiddle];
It works great, but I'd like to avoid the target row from being "selected". See image below:
Any ideas on how to "deselect" the row after this code runs? Or better yet, run this code in a way that doesn't "select" the target row in the first place?

[self.listTableView scrollToRowAtIndexPath:topIndexPath
atScrollPosition:UITableViewScrollPositionTop animated:YES];

Related

tvOS UITableView scroll to cell

I'm starting a new project for tvOS. I have created a programmatically UITableView inside my viewcontroller. Inside the UITableView i have created 5 cells. Until now everything works, but the problem happens when i'm trying to programmatically scroll to cell 4 so i'm doing:
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:3
inSection:0];
[tableView scrollToRowAtIndexPath:indexPath
atScrollPosition:UITableViewScrollPositionTop
animated:YES];
But the code above does nothing. It always start at first cell and highlight it as the selected one. I want to be able to programmatically start at another cell and it most be highlight so when i use the arrow keys down or up it scroll from there and not first cell. Please help me in doing that
You should do next:
In viewController that respond for UITableView, implement next function:
- (UIView *)preferredFocusedView {
return self.tableView;
}
where tableView is your table, and after that, override next function
- (NSIndexPath *)indexPathForPreferredFocusedViewInTableView:(UITableView *)tableView {
return [NSIndexPath indexPathForRow:_exerciseIndex inSection:0];
}
where _exerciseIndex index that you need to focus.

Custom Tableview getting crash in iPhone5(iOS7)

In my app i am using two table one for filter the data and second for results data. I am using the following line to scroll the tableview at selected index position,
self.indexPaths = [NSIndexPath indexPathForRow:0 inSection:indexPath.row];
[tableview scrollToRowAtIndexPath:self.indexPaths atScrollPosition:UITableViewScrollPositionTop animated:YES];
[tableview reloadData];
but my app is getting crash in only in iPhone5(iOS7) and working fine in all devices even iPhone5(iOS6).
Why does this crash only on iPhone5(iOS7)?
Crashing log is: Terminating app due to uncaught exception 'NSInvalidArgumentException'
You pass integer (0) for index path. You should pass NSIndexPath instead, try:
NSIndexPath *ip = [NSIndexPath indexPathForRow:0 inSection:0];
[tableview scrollToRowAtIndexPath:ip atScrollPosition:UITableViewScrollPositionTop animated:NO];
NSIndexPath is an object so you can't pass 0.
Try [NSIndexPath indexPathWithIndex:0]
self.indexPaths = [NSIndexPath indexPathForRow:0 inSection:indexPath.row];
the RHS returns the indexpath corresponding to a row and section.
in the above code,
you are passing indexpath.row to inSection parameter. This may be wrong.Assume, you have 1 section and 5 rows. when indexpath.row = 4(for eg), there wont be a section corresponding to 4 and hence self.indexPaths becomes nil since the system would try to look for row 4 in section 4, but section 4 doesnt exist!!
Consequently, when you pass nil to below line, it says nsinvalidargument exception.
tableview scrollToRowAtIndexPath:self.indexPaths atScrollPosition:UITableViewScrollPositionTop animated:YES];

Keep selected cell on heavily reloadRowsAtIndexPaths UITableView

In one of the views there is a UITableView which is getting updated rather often.
Tracking the changes are done in a classic way using "reloadRowsAtIndexPaths"
-(void)refreshCells:(NSArray *)changedCells
{
NSLog(#"refreshCells %i",[changedCells count]);
[TableView beginUpdates];
[TableView reloadRowsAtIndexPaths:changedCells withRowAnimation:UITableViewRowAnimationBottom];
[TableView endUpdates];
}
Question: How can I preserve the user's last selected Cell. the cell position may change after each update refreshCells?
You can save the current selection with
NSIndexPath *selectedRow = [self.tableView indexPathForSelectedRow];
before the reload and select it again with
if (selectedRow) {
[self.tableView selectRowAtIndexPath:selectedRow animated:NO scrollPosition:UITableViewScrollPositionNone];
}
after the reload. The cell position does not change unless you call insertRowsAtIndexPaths: or deleteRowsAtIndexPaths:.

iOS UItableview scrollToRowAtIndexPath not working anymore

This morning I just installed new Xcode which includes iOS 6.
I have a table view loaded with a plist file containing chapters and lines. Chapters define the sections.
The user selects chapter and line and the tableview is automatically scrolled to the correct position (in the viewDidLoad).
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:linePos inSection:chapterPos];
[self.tableView scrollToRowAtIndexPath:indexPath
atScrollPosition:UITableViewScrollPositionTop animated:YES];
this works just great in iOS5 simulator.
Trying this in the iOS 6 simulator the scroll is not performed. I get no errors. I have checked, linePos and chapterPos receive correct values but the scroll is not performed.
Any ideas why ?
Objective-C:
[self.tableView reloadData];
dispatch_async(dispatch_get_main_queue(), ^{
NSIndexPath *rowIndexPath = [NSIndexPath indexPathForRow:3 inSection:0];
[self.tableView scrollToRowAtIndexPath:rowIndexPath atScrollPosition:UITableViewScrollPositionMiddle animated:YES];
});
Swift:
tableView.reloadData()
DispatchQueue.main.async {
let indexPath = IndexPath(row: linePos, section: chapterPos)
self.tableView.scrollToRow(at: indexPath, at: .top, animated: true)
}
For recent versions of iOS, please read Fyodor Volchyok's answer. Note that it's not marked as the accepted answer simply because at the time the question was first asked (Sept. 2012), the current answer was the working solution.
More recent versions of iOS also got the same problem which is now solved by Fyodor Volchyok's answer, so you should +1 his answer at that moment.
I found the answer. I have to first reload the data in the tableview
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:linePos inSection:chapterPos];
[self.tableView reloadData];
[self.tableView scrollToRowAtIndexPath:indexPath
atScrollPosition:UITableViewScrollPositionTop animated:YES];
Even though I found the answer I don't know why it is working in iOS5 and not in iOS6.
EDIT
Perhaps I should add that even though it was working, I was still having a problem in displaying the last row and posted a question for that
UItableview scrollToRowAtIndexPath not displaying last row correctly
As #Raj also asked for it, I should say that I was triggering that in the viewDidLoad. To correct the problem of the last row not displaying correctly I had to put it in the viewDidAppear.
This works in iOS 12 and 13:
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
self.tableView.scrollToRow(at: IndexPath(row: 0, section: 1), at: .bottom, animated: true)
}
I ran into another issue (probably a bug) with scrollToRowAtIndexPath specifically on an iPhone X running ios11. My table has a few hundred sections and in collapsed mode ~10 would fit in the visible screen. As the indexPath got deeper, the scrolling gradually fell behind.
For example, when I wanted the search to find the item in row 30, the ScrollPositionTop would have one additional row before the actual row I expect to be at the top.
And as I tested searching for deeper rows, it started falling behind even more where for say anything past 100 rows deep or so, the expected row did not even come in the visible area.
The workaround I found so far is to say animated:NO for the scrolling within dispatch_async, then it works without any glitches.
I'm adding this answer as an addition to Fyodor Volchyok's answer. I also found that dispatching solves the issue. I was able to find a workaround that doesn't dispatch.
self.tableView.reloadData()
let index = // the desired index path
// For some reason, requesting the cell prior to
// scrolling was enough to workaround the issue.
self.tableView.cellForRowAtIndexPath(index)
self.tableView.scrollToRowAtIndexPath(index, atScrollPosition: .Top, animated: false)
After iOS7 the property automaticallyAdjustsScrollViewInsets of UIViewController default is YES. It will cause system to adjust the contentOffset of tableView when the view controller pushed. Even you call [self.tableView scrollToRowAtIndexPath:rowIndexPath atScrollPosition:UITableViewScrollPositionNone animated:NO]; in the viewWillAppear. The contentOffset also will be changed by system after viewWillAppear. So my solution is:
- (void)viewDidLoad {
[super viewDidLoad];
self.automaticallyAdjustsScrollViewInsets = NO;
/// any other codes
}
- (void)viewWillLayoutSubviews {
self.tableView.contentInset = UIEdgeInsetsMake(self.topLayoutGuide.length, 0, 0, 0);
}
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
// change tableView data source
[self.tableView reloadData];
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:[self.dataSourceArray count] - 1 inSection:0];
[self.tableView scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionNone animated:NO];
}
One more possible workaround is to call layoutIfNeeded before calling scrollToRowAtIndexPath.
[self.view layoutIfNeeded];
[self.tableView scrollToRowAtIndexPath...];
It worked for me in ios11
self.tableView.estimatedRowHeight = 0;
self.tableView.estimatedSectionFooterHeight = 0;
self.tableView.estimatedSectionHeaderHeight = 0
dispatch_async(dispatch_get_main_queue(), ^{
NSInteger numberOfSections = self.tableView.numberOfSections;
if (numberOfSections > 0)
{
NSInteger lastSection = numberOfSections - 1;
NSInteger lastRowInLastSections = [self.tableView numberOfRowsInSection:lastSection] - 1;
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:lastRowInLastSections inSection:lastSection];
[self.tableView scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionBottom animated:isAnimated];
}
});
Fyodor Volchyok's answer in Swift:
tableView.reloadData()
let indexPath = NSIndexPath(forRow: linePos, inSection: chapterPos)
// make sure the scroll is done after data reload was finished
dispatch_async(dispatch_get_main_queue()) {
self.tableView.scrollToRowAtIndexPath(indexPath, atScrollPosition: .Top, animated: true)
}

-[UITableView scrollToRowAtIndexPath:] scrolls, but goes back to 1st row

I have a grouped table view with textfields in the tableview. For the keyboard to not hide the textfields, in the textFieldShouldBeginEditing, I am calling the scrollToRowAtIndexPath method and setting the scroll position of the row being edited to the top of the tableview.
The scrolling does happen, but as soon as the keyboard appears (ie as soon as the textFieldShouldBeginEditing returns YES), the table scrolls back to its original position and displays the first row of the first section on top. I am not calling reloadTable after making a call to scrollToRowAtIndexPath.
The problem occurs only for row 4 and 5 (bdate and zip) password2 works as expected.
This is the code I am using to scroll to a particular row
if(textField == password2){
indPath = [NSIndexPath indexPathForRow:3 inSection:0];
[self.tableView scrollToRowAtIndexPath:indPath atScrollPosition:UITableViewScrollPositionTop animated:YES];
return YES;
}
else if(textField == bdate){
indPath = [NSIndexPath indexPathForRow:4 inSection:0];
[self.tableView scrollToRowAtIndexPath:indPath atScrollPosition:UITableViewScrollPositionTop animated:YES];
return YES;
}
else if(textField == zip){
indPath = [NSIndexPath indexPathForRow:5 inSection:0];
[self.tableView scrollToRowAtIndexPath:indPath atScrollPosition:UITableViewScrollPositionTop animated:YES];
return YES;
}
Can someone please tell me what could be going wrong? Any insight would help.
Thanks
I suspect what is going on is that the table view is rubber banding back, just like a webview in Safari does when you run pass its bounds. The most likely reason for this is that when you pop up the keyboard it is on top of the table view, but the table view has not physically contracted, thus all the UITableViewCells fit within the partially obscured UITableView, and when some of them scroll off it rubber bands so they all are within it.
In order to test this try reducing the size of the list view so that you can see the whole thing when the keyboard is displayed, if the bug goes away you want to write code that dynamically changes the size as the keyboard animates in and out.
//For iOS 7
[self.TableView reloadData];
NSIndexPath *indexPat = [NSIndexPath indexPathForRow:1 inSection:1];
[self.TableView scrollToRowAtIndexPath:indexPat atScrollPosition:UITableViewScrollPositionTop animated:YES];