Интерактивно снимите выделение выбранного UITableViewCell с обратным жестом

В приложениях iOS 7 (например, "Настройки" ), когда вы нажимаете на строку, например "Общие", затем прокручиваете слева от экрана, вы можете отменить выделение выбранного цвета фона фона строки от серого до белого, и он полностью интерактивен - если вы проведите пальцем пополам, а затем отведите назад, он станет серым.

В моем приложении я не изменил никакого поведения по умолчанию, и когда я прокручиваю слева, чтобы вернуться назад, выбранный цвет фона ячейки остается полностью серым до тех пор, пока жестом салфетки не будет завершен, а затем он быстро исчезнет белый.

Как реализовать интерактивный отбор строк с помощью салфетки, чтобы вернуться назад?

Ответ 1

В версиях iOS до 11 добавление [self.tableView deselectRowAtIndexPath:[self.tableView indexPathForSelectedRow] animated:YES]; работало чудесно, чтобы включить интерактивный отбор выбора ячейки. Спасибо @Dima за это!

Как и в iOS 11, из-за изменений с интерактивными переходами это больше не работает. Чтобы включить интерактивный отбор на iOS 11+, вы можете использовать UITableViewController, потому что он реализует его для вас, иначе вы можете реализовать его, оживив отмена выбора вместе с координатором перехода, например:

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

    NSIndexPath *selectedIndexPath = [self.tableView indexPathForSelectedRow];
    if (selectedIndexPath != nil) {
        if (self.transitionCoordinator != nil) { 
            [self.transitionCoordinator animateAlongsideTransition:^(id<UIViewControllerTransitionCoordinatorContext> context) { 
                [self.tableView deselectRowAtIndexPath:selectedIndexPath animated:YES]; 
            } completion:^(id<UIViewControllerTransitionCoordinatorContext> context) { 
                 if (context.cancelled) { 
                     [self.tableView selectRowAtIndexPath:selectedIndexPath animated:NO scrollPosition:UITableViewScrollPositionNone]; 
                 } 
            }]; 
        } else { 
             [self.tableView deselectRowAtIndexPath:selectedIndexPath animated:animated]; 
        }
    }
}

И в Swift:

override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)

    if let selectedIndexPath = tableView.indexPathForSelectedRow {
        if let coordinator = transitionCoordinator {
            coordinator.animate(alongsideTransition: { context in
                self.tableView.deselectRow(at: selectedIndexPath, animated: true)
            }) { context in
                if context.isCancelled {
                    self.tableView.selectRow(at: selectedIndexPath, animated: false, scrollPosition: .none)
                }
            }
        } else {
            self.tableView.deselectRow(at: selectedIndexPath, animated: animated)
        }
    }
}

Ответ 2

Кажется, что clearsSelectionOnViewWillAppear действительно может быть вызван viewDidAppear:, а не viewWillAppear:. Изменение происходит только после полного завершения перехода, и если вы отмените интерактивный переход, это не произойдет вообще (если это было в viewWillAppear:, это было бы). Это выглядит как ошибка UIKit, поскольку документы четко заявляют, что она должна быть вызвана в viewWillAppear:

Поместите следующую строку кода в viewWillAppear:, и вы получите точное поведение, которое вы ищете, я просто попробовал. Вероятно, это точное поведение, которое запускает свойство, только в неправильном методе.

[self.tableView deselectRowAtIndexPath:[self.tableView indexPathForSelectedRow] animated:YES];