快速向后滑动时,UITableViewCell不会被取消选中

Rob*_*ert 59 uitableview ios ios7

我现在已经将我的三个应用程序更新到了iOS 7,但是在这三个应用程序中,尽管它们没有共享任何代码,但我遇到的问题是,如果用户滑动以返回导航控制器(而不是快速点击后退按钮) ,细胞将保持其选定状态.

对于这三个应用程序,一个使用以编程方式创建的自定义单元格,另一个使用在故事板中创建的自定义单元格,第三个使用UITableView的一个非常基本的子类中的默认单元格,也在故事板中.在所有三种情况下,细胞不会自行取消选择.如果用户缓慢滑动或按下后退按钮,则会正常取消选择.

这只发生在我的iOS 7应用程序中,Apple自己的应用程序和为iOS 7升级的第三方应用程序似乎都表现正常(虽然细胞取消选择的速度略有不同).

一定有什么我做错了,但我不确定是什么?

小智 54

这对我来说效果最好:

- (void)viewDidLoad {
    [super viewDidLoad];
    self.clearsSelectionOnViewWillAppear = NO;
}

-(void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];
    [self.tableView deselectRowAtIndexPath:[self.tableView indexPathForSelectedRow] animated:animated];
}
Run Code Online (Sandbox Code Playgroud)

当我慢慢地向后滑动时,我甚至有一个更好的未选择性褪色.

  • 我在另一个答案中解决了"半滑,然后取消"的问题. (3认同)

Fab*_*oni 36

我现在正处理同样的问题.来自Apple 的UICatalog -sample似乎带来了肮脏的解决方案.

它真的不会让我开心.如前所述,它用于[self.tableView deselectRowAtIndexPath:tableSelection animated:NO];取消选择当前选定的行.

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

    // this UIViewController is about to re-appear, make sure we remove the current selection in our table view
    NSIndexPath *tableSelection = [self.tableView indexPathForSelectedRow];
    [self.tableView deselectRowAtIndexPath:tableSelection animated:NO];

    // some over view controller could have changed our nav bar tint color, so reset it here
    self.navigationController.navigationBar.tintColor = [UIColor darkGrayColor];
}
Run Code Online (Sandbox Code Playgroud)

我不得不提一下示例代码 IOS 7 iOS 8 iOS 9 iOS 10准备好了


真正令我困惑的是UITableViewController类参考:

当表视图即将在第一次加载时出现时,表视图控制器会重新加载表视图的数据.每次显示表格视图时,它还会清除其选择(有或没有动画,具体取决于请求).UITableViewController 类的超类方法实现这个viewWillAppear:.您可以通过更改clearsSelectionOnViewWillAppear属性中的值来禁用此行为 .

这正是我期望的行为......但它似乎不起作用.既不适合你,也不适合我.我们真的必须使用"脏"的解决方案,并自己做.

  • 我无法相信这仍然是iOS 9的一个问题. (34认同)
  • 我无法相信这仍然是iOS 8的一个问题. (26认同)
  • 我无法相信这仍然是iOS 10的一个问题. (23认同)
  • 我无法相信这仍然是iOS 11的一个问题 (7认同)
  • 很高兴我不是唯一这么认为的人,我已经提交了一个错误. (3认同)
  • 我不敢相信这仍然是 iOS 11.4.1 的问题。 (2认同)

Rhu*_*ult 19

Fabio的答案效果很好,但如果用户只是稍微滑动然后改变主意就不会给出正确的效果.为了使这种情况正确,您需要保存选定的索引路径并在必要时重置它.

- (void)viewDidAppear:(BOOL)animated
{
    [super viewDidAppear:animated];
    self.savedSelectedIndexPath = nil;
}

- (void)viewWillDisappear:(BOOL)animated
{
    [super viewWillDisappear:animated];
    if (self.savedSelectedIndexPath) {
        [self.tableView selectRowAtIndexPath:self.savedSelectedIndexPath animated:NO scrollPosition:UITableViewScrollPositionNone];
    }
}

- (void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];
    self.savedSelectedIndexPath = self.tableView.indexPathForSelectedRow;

    if (self.savedSelectedIndexPath) {
        [self.tableView deselectRowAtIndexPath:self.savedSelectedIndexPath animated:YES];
    }
}
Run Code Online (Sandbox Code Playgroud)

如果使用UITableViewController,请确保禁用内置清除:

self.clearsSelectionOnViewWillAppear = NO;
Run Code Online (Sandbox Code Playgroud)

并为savedSelectedIndexPath添加属性:

@property(strong, nonatomic) NSIndexPath *savedSelectedIndexPath;
Run Code Online (Sandbox Code Playgroud)

如果你需要做这在几个不同的类别,可能是有意义的像我在这个要点做是出于分裂的帮手,例如:https://gist.github.com/rhult/46ee6c4e8a862a8e66d4

  • 我不敢相信这不是UITableViewController的默认实现... (2认同)

nev*_*ing 9

此解决方案为行取消选择和转换协调器(用于用户驱动的VC解除)设置动画,并在用户取消转换时重新应用选择.改编自Ciftb Davenport在Swift中的解决方案.仅在iOS 9上测试.经测试同时使用用户驱动(滑动)过渡和旧式"后退"按钮.

UITableViewController子类中:

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

    // Workaround. clearsSelectionOnViewWillAppear is unreliable for user-driven (swipe) VC dismiss
    NSIndexPath *indexPath = self.tableView.indexPathForSelectedRow;
    if (indexPath && self.transitionCoordinator) {
        [self.transitionCoordinator animateAlongsideTransition:^(id<UIViewControllerTransitionCoordinatorContext>  _Nonnull context) {
            [self.tableView deselectRowAtIndexPath:indexPath animated:animated];
        } completion:^(id<UIViewControllerTransitionCoordinatorContext>  _Nonnull context) {
            if ([context isCancelled]) {
                [self.tableView selectRowAtIndexPath:indexPath animated:NO scrollPosition:UITableViewScrollPositionNone];
            }
        }];
    }
}
Run Code Online (Sandbox Code Playgroud)


小智 7

在我今天遇到这个问题之后,我发现这显然是UITableView的一个相当着名的问题,它对交互式导航过渡的支持略有破坏.卡斯特罗背后的人们已经发布了一个很好的分析和解决方案:http://blog.supertop.co/post/80781694515/viewmightappear

我决定使用他们的解决方案,也考虑取消转换:

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

    NSIndexPath *selectedRowIndexPath = [self.tableView indexPathForSelectedRow];
    if (selectedRowIndexPath) {
        [self.tableView deselectRowAtIndexPath:selectedRowIndexPath animated:YES];
        [[self transitionCoordinator] notifyWhenInteractionEndsUsingBlock:^(id<UIViewControllerTransitionCoordinatorContext> context) {
            if ([context isCancelled]) {
                [self.tableView selectRowAtIndexPath:selectedRowIndexPath animated:NO scrollPosition:UITableViewScrollPositionNone];
            }
        }];
    }
}
Run Code Online (Sandbox Code Playgroud)


fal*_*ypt 5

你可以尝试设置

self.clearsSelectionOnViewWillAppear = YES;
Run Code Online (Sandbox Code Playgroud)

在UITableViewController或

[self.tableView deselectRowAtIndexPath:[self.tableView indexPathForSelectedRow] animated:NO];
Run Code Online (Sandbox Code Playgroud)

在viewWillAppear中,也许在调用[super viewWillAppear:animated]之前; 如果您的UItableView 不在 UITableViewController中,则必须手动取消选择单元格:

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    [tableView deselectRowAtIndexPath:indexPath animated:YES]; 
}
Run Code Online (Sandbox Code Playgroud)

  • `self.clearsSelectionOnViewWillAppear = YES;`不起作用,虽然我预料到,因为那是默认的.`[self.tableView deselectRowAtIndexPath:[self.tableView indexPathForSelectedRow] animated:animated];`inside` - (void)viewWillAppear:(BOOL)animated`(在调用`super`之后)确实有效,但是我很困惑为什么这是必要.当我在`viewWillAppear:`中调用`super`时,表视图控制器不应该这样做吗?为什么它只影响拖动模式而不是标准的"点击后退按钮"? (2认同)