UITableViewCells从segue返回时不会取消选中状态

21

我有一个在Storyboard中的UITableView,其中包含单元格,并且通过segue将这些单元格与另一个视图连接。

当您选择一个单元格时,它会显示单元格选择动画(在我的情况下是将单元格变为灰色),并将另一个视图推到屏幕上。但是当您返回到tableview时,反选动画根本不会显示(即选择动画的相反作用)。由于我只是使用了segue,所以我希望它能默认处理此问题。

是否有任何方法强制显示反选动画?


在这里找到了解决方案:https://dev59.com/rXI-5IYBdhLWcg3weoFO。 - Nathan Fraenkel
6个回答

26
如果您的视图控制器是UITableViewController的子类,并且已将clearsSelectedOnViewWillAppear设置为YES(默认值),则会自动处理这个问题。
在您的情况下,您可以像UITableViewController一样执行此操作。 在-viewWillAppear:中取消选择所选行。
- (void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];
    NSIndexPath *selectedIndexPath = [self.tableView indexPathForSelectedRow];
    [self.tableView deselectRowAtIndexPath:selectedIndexPath animated:YES];
}

我的视图控制器是UITableViewController的子类。当它被显示时,单元格会被取消选择,但它不会显示动画 - 它一开始就被取消选择了。(以防万一,我尝试了你建议的方法,但没有起作用。) - Evan Cordell
刚刚创建了一个样例项目,其中包含一个位于UINavigationController中的 UITableViewController,该控制器通过 segues 切换到另一个视图控制器。所有组件都是使用 storyboard 进行设置的,并且返回到前一个视图控制器时显示取消选择动画。也许原始视图控制器的视图正在卸载,因此表格的选择状态丢失。这可能会在内存压力较大的情况下发生。 - Mark Adams
我的应用按照你的描述设置(但也带有选项卡),并使用核心数据(Core Data)。现在大部分请求只有两到三条记录(仅用于测试),所以我认为它不会对内存资源造成负担。 - Evan Cordell
这段代码是正确的,并且在Interface Builder中有一个选项(选择UITableViewController而不是TableView)“出现时清除”。 - Oli
无论是否选中该选项,我都会得到相同的行为。 - Evan Cordell
UITableViewController 中没有名为clearsSelectedOnViewWillAppear的属性。你是不是想说 clearsSelectionOnViewWillAppear - Pang

11

请确保调用了viewWill...viewDid...方法的super实现


我在每个继承的方法中都这样做。 - Evan Cordell
你是怎么返回到你的UITableViewController的?你是否使用在storyboard中使用push转场时自带的默认返回按钮? - John Estropia
我是。我的UITableViewController在UINavigationController中,当我使用导航控制器创建的返回按钮从详细视图返回到表视图时。(并且segue是“push”类型) - Evan Cordell
我正在按照你描述的方式进行,但从未遇到过这样的问题。不知道你的控制器行为是怎样的,很难说,但我正在思考一些想法。你确定你要弹出的是同一个视图控制器实例吗?你可以在UITableViewController的viewDidAppear:viewDidDisappear:上执行NSLog(@"%@", self);来测试这个问题。 - John Estropia
它是相同的控制器实例。 - Evan Cordell

11

我不确定segue的用法,但我经常想在视图控制器出现时刷新数据。然而,如果您重新加载表格,将清除选择行。这是我使用的一些代码,用于保持选定行并在返回时显示取消选择动画。也许这可以帮助您,所以我会在这里发布它。

-(void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];

    NSIndexPath *indexPath = [tableView indexPathForSelectedRow];
    [tableView reloadData];
    if(indexPath) {
        [tableView selectRowAtIndexPath:indexPath animated:NO scrollPosition:UITableViewScrollPositionNone];
    }
}

-(void)viewDidAppear:(BOOL)animated {
    [super viewDidAppear:animated];

    NSIndexPath *indexPath = [tableView indexPathForSelectedRow];
    if(indexPath) {
        [tableView deselectRowAtIndexPath:indexPath animated:YES];  
    }
}

我确实重新加载了表格数据,但你的解决方案并没有起作用。(我之前已经尝试过它,但为了确保我又尝试了一次。) - Evan Cordell
你在其他地方重新加载表格了吗?同时,请确保在调用viewWillAppear之前不要删除所选行。根据数据的更改方式,重新选择相同的行可能对你没有作用。 - Chase
我接受了这个,尽管我从未解决过这个问题。我想我一定在某个地方重新加载了。 - Evan Cordell

5

针对 Swift 3

override func viewWillAppear(_ animated: Bool) {

    super.viewWillAppear(animated)
    if let path = tableView.indexPathForSelectedRow {

        tableView.deselectRow(at: path, animated: true)
    }
}

1
更好的Swift更新:
 override func viewWillAppear(animated: Bool) {
    super.viewWillAppear(animated)

    if let path = tableView.indexPathForSelectedRow {

        tableView.deselectRowAtIndexPath(path, animated: true)
    }
}

1

Swift 更新:

override func viewDidAppear(animated: Bool) {
    super.viewDidAppear(true)
    if tableView.indexPathForSelectedRow != nil {
        let indexPath: NSIndexPath = tableView.indexPathForSelectedRow!
        tableView.deselectRowAtIndexPath(indexPath, animated: true)
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接