I have a UITableView on a view. This UITableView has cells which are made up of a checkbox custom control, a label and a disclosure accessory. When I select a row in the tableview it selects correctly (blue highlight shows 100% correctly).
I then created a didSelectRowAtIndexPath delegate to push a detail view controller onto the navigation stack using the following code:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
MyDetailsViewController *detailsViewController = [[MyDetailsViewController alloc] initWithNibName:#"MyDetailsView" bundle:nil];
[[self navigationController] pushViewController:detailsViewController animated:YES];
[detailsViewController release];
}
This works - in so far as that it pushes the view controller onto the navigation stack and presents the view. The problem I'm having is that the animation is really "flickery" and the row that was selected doesn't even get highlighted before the animation starts.
I've done this before (but never with custom cells) and I know that the procedure should be as follows: row highlights, detail view animates in, (edit details), detail view animates out, row gets deselected.
I'm not sure why my row automatically gets deselected (or de-highlighted) when I select it and why the animation is flickery.
Has anyone had this before?
Ugh, I so hate it when I find the answer to my own question about a minute after posting it. The problem was that I was doing all kinds of things in viewWillDisappear that was modifying my table data. ****grin****
Related
I have an app I am working on, that has a table view with a few cells, and when you hit a cell, the nav controller pushes a new view. Pretty simple stuff. The problem is that when I hit on a row, the whole row highlights blue, and then remains blue all while the view is being presented by the controller, and then if I hit back to go back to the table view, the row is just still completely highlighted Even though I'm not pressing it or anything.
I have made a few apps with the table view before, and have never seen this behavior before, so I am at a loss as to what is going on. Is there some setting that I have set wrong somewhere?
Thanks
You need to deselect cell manually (probably in tableView:didSelectRowAtIndexPath: method):
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
[tableView deselectRowAtIndexPath:indexPath animated:YES];
// Your code
...
}
If your view controller is a subclass of UITableViewController, it will automatically deselect the row after you hit the back button. If you don't subclass UITableViewController, you need to call deselectRowAtIndexPath:animated: when you want it deselected.
in my program I need a tableview and, when you click onto a row, the view scroll left and show the details (like the mail for example...)
how can I do this??
I explain... it's an automatic thing or I need to manage by hand the animation of the view??
thanks in advance
I use UINavigationControllers to achieve this effect of the detail animating left when you click on the row. So you need a UINavigation controller above the UIViewController or UITableView Controller that controls your table.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
...my code
[self.navigationController pushViewController:myViewController animated:YES];
}
Your case is exactly what UINavigationController class is for - it will handle your controllers hierarchy and will do animated transition for you as well. To learn how to use it you can have a look at Apple's NavBar sample.
I have a cell with a few lines of text which changes colour when selected/highlighted. The problem is that as the new viewController is being pushed, the deselection animation occurs which is visually distracting as the text suddenly reverts to the unselected state. I have moved the deselectRowAtIndexPath statement after the line where the new view controller is pushed, but this has no effect.
How can I prevent the user seeing the cell deselection (without implementing a timer)? Any help would be appreciated please.
If you're using a UITableViewController, you won't need to call deselectRowAtIndexPath:. This will be done for you automatically when your table view becomes visible again.
If you're not using a UITableViewController because you have a more complicated interface, you would need to call deselectRowAtIndexPath: manually from the viewWillAppear:animated: method.
I think the general paradigm used with table views and pushing new VCs is that you deselect the table row in your viewWillAppear:animated method. Then as the VC is popped, they see which row had been used to navigate to that VC.
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
[self.myTableView deselectRowAtIndexPath:[myTableView indexPathForSelectedRow] animated:YES];
}
so remove deselectRow from your didSelectRowAtIndexPath method.
When a button is pushed in one of my app's table view cells, I need to push a certain view controller onto the navigation stack.
This could be done by using an instance of NSNotification to inform the table view's controller of the button press. But that would be awfully heavyweight, especially since selections in a tab bar in the app could cause the table view to appear or disappear, creating additional overhead as the various table views register and unregister themselves whenever they are tabbed onto or off of the screen.
Can anyone think of a better solution?
Why not put
[[self navigationController] pushViewController:targetViewController animated:YES];
in the method called by the button?
Make your UITableViewController use the UITableViewDelegate Protocol and implement this method:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
From the indexPath you can get which row has been pressed and then you know which cell is being selected. The purpose of the UITableViewController is to know about the cells and the cell itself does not need a button to trigger an event to push a new view.
What I did was set the table view's delegate to be the same as its controller. Then:
UITableView *myTableView = (UITableView *)self.superview;
NSIndexPath *indexPath = [myTableView indexPathForCell: self];
MyTableViewController *myTableViewController = (MyTableViewController *)(myTableView.delegate);
[myTableViewController buttonWasPressedOnCellWithIndexPath: indexPath];
I have a navController and tableViewController set up such that selecting a table row will push a detail view on the navController's stack and display detailed information about the row selected. In the detail view I use a single UILabel to display the info, and I set the value of the label's text property in viewDidLoad of the detail view controller.
The first time I select a row, the detail view comes up with the expected text. When I go back to the table view and select a different row, the detail view comes up with the same text as the first time.
I have seen some code samples where the detail view controller is released and then set to nil after being pushed on the navController's stack. If I add that to my code, the problem goes away, but I don't understand why.
Can someone explain to me what's going on here?
Thanks!
-viewDidLoad is called only when the... well, when the view is loaded. That is to say, when it is created in memory, which is the first time you create the view controller. Any customizations based input data should be done in -viewWillAppear: instead, which gets called every time before you push it onto the navigation controller.
Although, in general practice, I always release a new view controller immediately after pushing it onto the stack, since it doesn't belong to me any more, it belongs to the navigation controller. In this case, the next time you push it on to the stack, it will load the view again, since it's a new object.
- (void) tableView:(TableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
UIViewController *screen = [[MyNewViewController alloc] initWithData:[data objectAtIndex:indexPath.row]];
[self.navigationController pushViewController:screen animated:YES];
[screen release];
}
The main idea, though, is that customizing a view based on data that may change every time you see the view should be done within -viewWillAppear:. Customizing a view further than you can in Interface Builder, changing things which won't change no matter what data you're looking at, should be done in -viewDidLoad