How to change clearsSelectionOnViewWillAppear when not using UITableViewController?
I have a UIViewController that manages a UISearchBar and UITab开发者_Go百科leView. I've read that Apple discourage having multiple UIViewControllers manage part of your application, so I did not used UITableViewController to manage the UITableView. Instead, I implemented the UITableViewDelegate
and UITableViewDataSource
protocol in my own UIViewController.
My question is, since I am no longer using UITableViewController, how do I actually change the clearsSelectionOnViewWillAppear
behavior? This property is part of UITableViewController.
Simply by calling
[myTableView deselectRowAtIndexPath:[myTableView indexPathForSelectedRow] animated:YES];
in your viewWillAppear:
method.
Here the Swift code:
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
if let indexPath = tableView.indexPathForSelectedRow() {
tableView.deselectRowAtIndexPath(indexPath, animated: true)
}
}
You are most likely overriding the viewWillAppear:animated
method and missing the [super viewWillAppear:animated]
call.
If you want an interactive animation:
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
NSIndexPath *selectedIndexPath = [self.tableView indexPathForSelectedRow];
if(selectedIndexPath) {
if(self.transitionCoordinator != nil) {
[self.transitionCoordinator animateAlongsideTransition:^(id<UIViewControllerTransitionCoordinatorContext> context) {
[self.tableView deselectRowAtIndexPath:selectedIndexPath animated:YES];
} completion:^(id<UIViewControllerTransitionCoordinatorContext> context) {
}];
[self.transitionCoordinator notifyWhenInteractionChangesUsingBlock:^(id<UIViewControllerTransitionCoordinatorContext> context) {
if(context.cancelled) {
[self.tableView selectRowAtIndexPath:selectedIndexPath
animated:YES
scrollPosition:UITableViewScrollPositionNone];
}
}];
} else {
[self.tableView deselectRowAtIndexPath:selectedIndexPath animated:animated];
}
}
}
Swift Version:
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
if let selectedIndexPath = self.tableView.indexPathForSelectedRow {
if let transitionCoordinator = self.transitionCoordinator {
transitionCoordinator.animate(alongsideTransition: { (context) in
self.tableView.deselectRow(at: selectedIndexPath, animated: true)
}, completion: nil)
transitionCoordinator.notifyWhenInteractionChanges { (context) in
if context.isCancelled {
self.tableView.selectRow(at: selectedIndexPath, animated: true, scrollPosition: .none)
}
}
} else {
self.tableView.deselectRow(at: selectedIndexPath, animated: animated)
}
}
}
Now you can scrub the animation, i.e. when interactively popping from a navigation controller. It also reselects the row if the interaction was cancelled. This is closer to what is happening inside UITableViewController
.
Updated for Swift 5:
override func viewWillAppear(_ animated: Bool) {
if let indexPath = tableView.indexPathForSelectedRow {
tableView.deselectRow(at: indexPath, animated: true)
}
self.tableView.reloadData()
}
精彩评论