Як скасувати вибір вибраної комірки 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
На це запитання потрібно мати прийняту відповідь
Титуан де Байєль

Відповіді:


407

використовувати цей код

- (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, який слід використовувати, щоб скасувати вибір попереднього.
huggie

3
Мені подобається думати, що я не можу підтвердити цю посаду, тому що це може спричинити переповнення цілого числа :)
Міло

привіт @ram, вам потрібно вибрати відповідь на це питання
Fattie

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
Хороша робота ... Я думаю, що "індекс" на другому рядку має бути 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 з декількома варіантами. Пальці вгору.
Danny Bravo

6

Це має працювати:

[tableView deselectRowAtIndexPath:indexpath1 animated:NO];

Просто переконайтеся, що materialTable та tableView вказують на один і той же об'єкт.

Чи підключені матеріали до tableView в Interface Builder?


Я перевірив NO, але це також не вирішує мою проблему. але я вирішив цю проблему іншим способом, як перезавантажені дані, коли коли-небудь делегат didselect звільнявся.
Рам

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 , щоб зберегти споріднені методи згруповані разом, покладіть це розширення нижче класу контролерів перегляду таким чином:

// 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, що рядок вже вибрано для початку, так що початковий клік потім скасує вибір рядка:

// Швидкий 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.