Im transferring my project from xibs to using a storyboard. I just added the Settings page, which i made from a UIViewController to a UITableViewController. The table view cells are added using the static method in the storyboard. The table has 5 sections, with 12 cells. I have no other code doing anything to the TableView, and in the storyboard scrolling is on. When running on my iPhone 5 the view wont scroll, all the cells are there, and i can pull and see the cells hidden, but when letting go it scrolls to the top still. Like when pulling up on a page in a UIWebView basically. Xcode gives no warnings, or errors, how can i fix this?
Edit: I found the 2 lines of code causing it not to scroll, But i still don't know how to fix it. The code gets the custom TextFieldTableCell and sets the text for it, because I'm using a storyboard, It doesn't call CellForRow,
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
TextFieldTableCell *cell = (TextFieldTableCell *)[SettingsTable cellForRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0]];
cell.textField.text = [[NSUserDefaults standardUserDefaults] objectForKey:#"Homepage"];
}
The TableView is only disabled from scrolling if the 2 lines under [super viewWillAppear:animated]; are called in the method - (void)viewWillAppear:(BOOL)animated, but if i call the lines in - (void)viewDidAppear:(BOOL)animated it will still scroll, except it takes a second to show that text, which isn't something i want, should be auto-loaded when user see's the TableViewController, are there any workarounds? Any other methods called like viewWillLoad but shouldn't disable the table?
Related
I have a single view with nested scroll and table view with this hierarchical tree:
(The table is loaded with some Huckleberry Finn rows taken from this example.)
On viewWillAppear I programmatically scroll the Table View at the last row doing
-(void)viewWillAppear:(BOOL)animated
{
[self.tableView reloadData];
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:[self.tableView numberOfRowsInSection:0]-1 inSection:0];
[self.tableView scrollToRowAtIndexPath:indexPath
atScrollPosition:UITableViewScrollPositionBottom
animated:YES];
}
and everything works as expected, in both orientation. As you can see, the text is rightly truncated.
I've uploaded on Github my project so you can see it running. Download it here.
Now, if you add this line in the cellForRowAtIndexPath method:
cell.textLabel.numberOfLines=0;
the cells automatically will resize to embed and show the entire text label:
BUT, and this is the issue my dear friends, as you can see the table is not scrolled to the last row but 5-6 rows above. And I cannot understand why.
The same thing happens also if NumberOfLines is 2,3 and so on. Only a value of 1 can make the TableView move down to the very last row.
(FYI, I do not use [self.tableView setContentOffset:CGPointMake(0, CGFLOAT_MAX)]; in order to scroll down the table because it throws an exception)
Maybe something is wrong with iOS8 ?
viewDidLayoutSubviews will do the job
I guess you use some autolayout or self sizing cells? In viewWillAppear the calculation is not finished. So you scroll to the bottom, but then thereafter autolayout resizes your cells what makes them expand in height.
For Details: Refer to apple documentation UIViewController
... "Your view controller can override this method to make changes after the view lays out its subviews. The default implementation of this method does nothing."
- (void)viewDidLayoutSubviews {
// your code here
}
I added this event with reloadSection method and now the table scroll to the end. Also, I changed "tableView" to "myTableView" since I read that is better to give a non-default name to the views (as Sapi says in his answer here).
- (void)viewDidLayoutSubviews {
[self.myTableView reloadSections:[NSIndexSet indexSetWithIndex:0] withRowAnimation:UITableViewRowAnimationAutomatic];
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:[self.myTableView numberOfRowsInSection:0]-1 inSection:0];
[self.myTableView scrollToRowAtIndexPath:indexPath
atScrollPosition:UITableViewScrollPositionBottom
animated:YES];
}
IMHO this thing is very Machiavellian, however.
I've got an UITableViewCell with a UITextField in it. When I click the UITextField I want to make sure the entire cell is visible in the tableView. I did this in textfieldDidBeginEditing, like so:
- (void) textFieldDidBeginEditing:(id)textField {
TTTableViewCell *cell = (TTTableViewCell *)[self.tableView cellForRowAtIndexPath:objc_getAssociatedObject(textField, kIndexPathId)];
[self.tableView setContentOffset:CGPointMake(cell.frame.origin.x, cell.frame.origin.y - self.tableView.sectionHeaderHeight) animated:YES];
}
This works perfectly when the user goes down the list. Expect when to user taps a cell which is partial visible on the top it doesn't reveal the entire cell just moves a bit.
Does someone know a solution to this problem?
There are UITableView methods to solve exactly this. You can use scrollToRowAtIndexPath:atScrollPosition:animated: to ask the table view to bring a cell to the top by passing UITableViewScrollPositionTop.
(You might first want to check if it's already visible to ensure it doesn't scroll unnecessarily.)
I have a UITableView which holds a number of choices and allows user to select one of these choices. I mark the selected row with a checkmark accessory.
On an iPad, I open this in a Pop over on click of a button and the table view shows up with one of the rows checked. But sometimes this checked row is not on screen and one needs to scroll to get to it. I would like to scroll to this checked row when I open the pop over. I have tried doing a scrollToRowAtIndexPath:atScrollPosition:animated: in viewDidAppear but I find that viewDidAppear is called before any call to cellForRowAtIndexPath and the scrolling to selected row doesn't happen
- (void)viewDidAppear:(BOOL)animated
{
NSLog(#"viewDidAppear called");
[super viewDidAppear:animated];
//currentSelectedIndexPath is a correct index path
[self.tableView scrollToRowAtIndexPath:currentSelectedIndexPath atScrollPosition:UITableViewScrollPositionMiddle animated:NO];
}
Try calling [self.tableView reloadData] just before scrolling in viewDidAppear.
I'm using code to create a detailed view pushed when you press a row of an UITableView, but theres a problem.
The detailed view contain an UITextView and when a detailedView is called (only first time) this make the UITableView row pressed to lose its pressed state. It shouldn't ! It should lose the pressed state only when returning from the detailed view to the list view.
As soon as I remove the UITextView from my code, no problem !
I think it's something like UITextView taking focus?
Is there any way to avoid this ? By subclassing or such?
Hmmm not seeing this in the sandbox I just wrote.
Created a simple navigation-based project.
Added a view controller to the project with XIB; added a UITextField to the XIB.
Made following code changes to the root view controller:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return 1;
}
in cellForRowAtIndexPath:
cell.text = #"Push me";
in didSelectRowAtIndexPath:
SimpleViewController *detailViewController = [[SimpleViewController alloc] initWithNibName:#"SimpleView" bundle:nil];
in viewDidLoad:
self.navigationItem.title = #"Home";
Selecting the "Push me" row highlights the row and pushes the SimpleViewController onto the stack. Selecting the "Home" back button pops the view off the stack, returning to the table view and deselecting/un-highlighting the selected row. This is true whether or not the textfield in the SimpleViewController is the first responder at the time of the back navigation.
I've got a UIViewController with a xib view that has a button and a table.
Everything is wired up, the data has rows in it etc. But if i click a row and navigate away from this initial screen, then go back, the cell in the table still has the highlighted state on it.
Do i need to implement methods other than numberOfSectionsInTableView, tableView:cellForRowAtIndexPath and tableView:didSelectRowAtIndexPath?
Implement -viewWillAppear: on your view controller and deselect the table's currently-selected row, something like this:
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
[self.tableView deselectRowAtIndexPath:[self.tableView indexPathForSelectedRow] animated:animated];
}