Как отменить выбор выбранной ячейки UITableView?


212

Я работаю над проектом, по которому мне нужно предварительно выбрать конкретную ячейку.

Я могу предварительно выбрать ячейку с помощью -willDisplayCell, но не могу отменить ее выбор, когда пользователь нажимает на любую другую ячейку.

- (void)tableView:(UITableView*)tableView 
        willDisplayCell:(UITableViewCell*)cell
        forRowAtIndexPath:(NSIndexPath*)indexPath
{ 
    AppDelegate_iPad *appDelegte = 
      (AppDelegate_iPad *)[[UIApplication sharedApplication] delegate];

    if ([appDelegte.indexPathDelegate row] == [indexPath row])
    {
        [cell setSelected:YES];    
    } 
}

- (void)tableView:(UITableView *)tableView 
        didSelectRowAtIndexPath:(NSIndexPath *)indexPath {

    AppDelegate_iPad *appDelegte = 
      (AppDelegate_iPad *)[[UIApplication sharedApplication] delegate];

    NSIndexPath *indexpath1 = appDelegte.indexPathDelegate;
    appDelegte.indexPathDelegate = indexPath;
    [materialTable deselectRowAtIndexPath:indexpath1 animated:NO];
}

Вы можете помочь?


11
На этот вопрос нужно иметь принятый ответ
Титуан де Байеул

Ответы:


408

используйте этот код

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath 
 {
    //Change the selected background view of the cell.
     [tableView deselectRowAtIndexPath:indexPath animated:YES];
 }

Swift 3.0:

override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
    //Change the selected background view of the cell.
    tableView.deselectRow(at: indexPath, animated: true)
}

1
Существует didDeselectRowAtIndexPath, который используется для отмены выбора предыдущего.
Хагги

3
Мне нравится думать, что я не могу проголосовать за этот пост, потому что это может привести к переполнению целого числа :)
Мило

привет @рам, тебе нужно выбрать ответ на этот вопрос
Толстяк

4
Я не понимаю ... этот код никогда не позволит выбрать что-либо.
C. Tewalt

@matrixugly прав. Это более уместно сделать это внутри willSelectRowAt:. Смотрите более полный ответ здесь: stackoverflow.com/questions/12693402/…
HuaTham

117

Используйте следующий метод в табличном представлении делегата didSelectRowAtIndexpath(или из любого места)

[myTable deselectRowAtIndexPath:[myTable indexPathForSelectedRow] animated:YES];

2
Стоит отметить, что indexPathForSelectedRowэто метод, а не свойство.
FreeAsInBeer

Сладкий! Не знал о [myTable indexPathForSelectedRow]. Я проходил через клетки раньше. Спасибо!
Гуптрон

@FreeAsInBeer Как-то важно это различие? Свойства доступа являются методами.
devios1

@chaiguy Это нормально, если вы не против своих коллег, считающих вас злом .
FreeAsInBeer

1
@Supertecnoboff Нет никакой разницы в производительности между этими двумя вариантами.
FreeAsInBeer

38

Попробуй это:

for (NSIndexPath *indexPath in tableView.indexPathsForSelectedRows) {
    [tableView deselectRowAtIndexPath:indexPath animated:NO];
}

1
Хорошая работа ... Я думаю, что 'index' во 2-й строке должен быть indexPath
El Tomato

это не поддерживается на iOS 11 Swift 4
Борис Николич

30

Для этого может быть полезно сделать расширение в Swift.

Swift 4 и Swift 5:

Расширение Swift (например, в файле UITableViewExtension.swift):

import UIKit

extension UITableView {

    func deselectSelectedRow(animated: Bool)
    {
        if let indexPathForSelectedRow = self.indexPathForSelectedRow {
            self.deselectRow(at: indexPathForSelectedRow, animated: animated)
        }
    }

}

Используйте, например:

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

    self.tableView.deselectSelectedRow(animated: true)
}

1
На мой взгляд, этот ответ лучше, потому что помещение в viewWillAppear()метод запустения помогает пользователю понять, откуда он возвращается.
MonsieurDart

идеальный, как мне нужно
Патель Джигар

28

Пожалуйста, уточните метод делегата, является ли он правильным или нет. Например;

-(void) tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath

для

-(void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath

Все это время вызывал неправильный метод, аааа !! Спасибо!
Дамир Которич,

1
о боже .... кровавое автозаполнение !!! Мне понадобилось несколько часов, чтобы понять это !!! OMG ... Я хочу поцеловать тебя!
Джордж Асда


16

Это решение для Swift 4

 in tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath)

просто добавь

tableView.deselectRow(at: indexPath, animated: true)

Работает как часы

пример:

func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        tableView.deselectRow(at: indexPath, animated: true)
//some code
}

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

Это, безусловно, правильный подход, когда вы не редактируете, когда вы «постукиваете по строке, чтобы что-то сделать»
Fattie

11

Помимо установки выбранной ячейки, вам также необходимо сообщить tableView, что ячейка выбрана. Добавьте вызов к -tableView:selectRowAtIndexPath:animated:scrollPosition:вашему willDisplayCell:методу: и вы сможете отменить его, как обычно.

- (void)tableView:(UITableView*)tableView 
  willDisplayCell:(UITableViewCell*)cell
forRowAtIndexPath:(NSIndexPath*)indexPath
{ 
    AppDelegate_iPad *appDelegte = (AppDelegate_iPad *)[[UIApplication sharedApplication] delegate];

    if ([appDelegte.indexPathDelegate row] == [indexPath row])
    {
        // SELECT CELL
        [cell setSelected:YES]; 
        // TELL TABLEVIEW THAT ROW IS SELECTED
        [tableView selectRowAtIndexPath:indexPath animated:NO scrollPosition:UITableViewScrollPositionNone];   
    } 
}

Обязательно используйте UITableViewScrollPositionNone, чтобы избежать нечетного поведения прокрутки.


1
Совершенно верно. Я думаю , что [cell setSelected:YES]можно было бы опустить: selectRowAtIndexPathбудет позаботится о клеточных selectedсостоянии
spassas

Этот ответ работает для UITableView с несколькими вариантами выбора. Недурно.
Дэнни Браво

6

Это должно работать:

[tableView deselectRowAtIndexPath:indexpath1 animated:NO];

Просто убедитесь, что materialTable и tableView указывают на один и тот же объект.

Связаны ли материалы с таблицей в Интерфейсном Разработчике?


Я проверил с НЕТ, но это также не решает мою проблему. но я исправил эту проблему другим способом, так как перезагружал данные, когда когда-либо выполнялся делегат didselect.
Ram

6

Основываясь на решении сайкиранов, я написал это, что мне помогло. В файле .m:

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {

    if(selectedRowIndex && indexPath.row == selectedRowIndex.row) {

        [tableView deselectRowAtIndexPath:indexPath animated:YES];
        selectedRowIndex = nil;

    }

    else {  self.selectedRowIndex = [indexPath retain];   }

    [tableView beginUpdates];
    [tableView endUpdates];

}

И в заголовочном файле:

@property (retain, nonatomic) NSIndexPath* selectedRowIndex;

Я не очень опытный, так что дважды проверьте утечки памяти и т. Д.


6

Если вы хотите выбрать любую ячейку таблицы одним щелчком мыши и отменить выбор вторым, вам следует использовать этот код:

- (void)tableView:(UITableView *)tableView 
        didSelectRowAtIndexPath:(NSIndexPath *)indexPath {   

    if (self.selectedIndexPath && 
        [indexPath compare:self.selectedIndexPath] == NSOrderedSame) {

        [tableView deselectRowAtIndexPath:indexPath animated:YES];
         self.selectedIndexPath = nil;
    } 
    else {
        self.selectedIndexPath = indexPath;
    }
}

5

Свифт 4:

func tableView(_ tableView: UITableView, willSelectRowAt indexPath: IndexPath) -> IndexPath? {
    let cell = tableView.cellForRow(at: indexPath)
    if cell?.isSelected == true { // check if cell has been previously selected
        tableView.deselectRow(at: indexPath, animated: true)
        return nil
    } else {
        return indexPath
    }
}

2
Это сработало для меня в Swift 3. Просто пришлось добавить self.tableView(tableView, didDeselectRowAt: indexPath)после, tableView.deselectRow...потому что он не вызывался автоматически
elysch


3

попробуй это

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

попробуйте объяснить свой ответ, иначе это должен быть комментарий.
Хьюго Дозойс

3
NSIndexPath * index = [self.menuTableView indexPathForSelectedRow];
[self.menuTableView deselectRowAtIndexPath:index animated:NO];

поместите этот код в соответствии с вашим кодом, и ваша ячейка будет снята.


3

Вы можете попробовать это?

- (void)tableView:(UITableView *)tableView 
  didSelectRowAtIndexPath:(NSIndexPath *)indexPath {

    AppDelegate_iPad *appDelegte = 
    (AppDelegate_iPad *)[[UIApplication sharedApplication] delegate];
    NSIndexPath *indexpath1 = appDelegte.indexPathDelegate;
    appDelegte.indexPathDelegate = indexPath;

    UITableViewCell *prevSelectedCell = [tableView cellForRowAtIndexPath: indexpath1];
    if([prevSelectedCell isSelected]){
       [prevSelectedCell setSelected:NO];
    }
}

Это сработало для меня.


2

Swift 3.0:

В соответствии с разделом о соответствии протоколов руководства по стилю ray wenderlich swift , чтобы объединить связанные методы, поместите это расширение под классом контроллера вида следующим образом:

// your view controller
class MyViewcontroller: UIViewController {
  // class stuff here
}

// MARK: - UITableViewDelegate
extension MyViewcontroller: UITableViewDelegate {
      // use the UITableViewDelegate method tableView(_:didSelectRowAt:)
    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {

        // your code when user select row at indexPath

        // at the end use deselectRow
        tableView.deselectRow(at: indexPath, animated: true)
    }
}

1

стриж

func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {

    // your code

    // your code

    // and use deselect row to end line of this function

    self.tableView.deselectRowAtIndexPath(indexPath, animated: true)

}

1
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
    tableView.deselectRow(at: indexPath, animated: true)
}

1

Свифт 3

Я также столкнулся с этим - когда вы переходите или возвращаетесь к табличному представлению, он обычно не отменяет ранее выбранную для вас строку. Я поместил этот код в контроллер табличного представления, и он работает хорошо:

override func viewDidAppear(_ animated: Bool) {
    if let lastSelectedRow = tableView.indexPathForSelectedRow {
        tableView.deselectRow(at: lastSelectedRow, animated: true)
    }
}

1

Свифт 3/4

В ViewController:

func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
    tableView.deselectRow(at: indexPath, animated: true)
}

В пользовательской ячейке:

override func awakeFromNib() {
    super.awakeFromNib()
    selectionStyle = .none
}


0

Отменить выделение (DidDeselectRowAt) при первом нажатии из-за предварительно загруженных данных; вам нужно сообщить tableView, что строка уже выбрана для начала, чтобы при первоначальном щелчке отмена выбора строки:

// Swift 3:

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

    if tableView[indexPath.row] == "data value"

        tableView.selectRow(at: indexPath, animated: false, scrollPosition: UITableViewScrollPosition.none)

    }
}

0

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

// Swift 3+  

override func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
    if appDelegate.indexPathDelegate.row == indexPath.row {
        self.tableView.selectRow(at: indexPath, animated: true, scrollPosition: .none)
        cell.setSelected(true, animated: true)
    }
}
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.