Jak odznaczyć wybraną komórkę UITableView?


212

Pracuję nad projektem, w którym muszę wstępnie wybrać konkretną komórkę.

Mogę wstępnie wybrać komórkę za pomocą -willDisplayCell, ale nie mogę jej odznaczyć, gdy użytkownik kliknie inną komórkę.

- (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];
}

Możesz pomóc?


11
To pytanie musi mieć zaakceptowaną odpowiedź
— Titouan de Bailleul

Odpowiedzi:


407

użyj tego kodu

- (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
Istnieje didDeselectRowAtIndexPath, którego można użyć do usunięcia zaznaczenia poprzedniego.
— huggie

3
Lubię myśleć, że nie mogę głosować za tym postem, ponieważ spowodowałoby to przepełnienie liczb całkowitych :)
— Milo,

cześć @ram, musisz wybrać odpowiedź na to pytanie
— Fattie,

4
Nie rozumiem ... ten kod nigdy nie pozwoli na wybranie niczego.
— C. Tewalt

@ matrixugly ma rację. Bardziej właściwe jest to zrobić w środku willSelectRowAt:.
— Pełniejszą

117

Użyj następującej metody w widoku tabeli delegata didSelectRowAtIndexpath(lub z dowolnego miejsca)

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

2
Warto zauważyć, że indexPathForSelectedRowjest to metoda, a nie właściwość.
— FreeAsInBeer

Słodkie! Nie wiedziałem o tym [myTable indexPathForSelectedRow]. Wcześniej zapętlałem komórki. Dzięki!
— guptron

@FreeAsInBeer Czy to rozróżnienie jest w jakiś sposób ważne? Accessory własności to metody.
— devios1

@chaiguy W porządku, jeśli nie masz nic przeciwko kolegom, którzy uważają cię za złego .
— FreeAsInBeer

1
@Supertecnoboff Nie ma różnicy w wydajności między tymi dwiema odmianami.
— FreeAsInBeer

38

Spróbuj tego:

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

1
Dobra robota ... Myślę, że „indeksem” w drugim wierszu powinien być indexPath
— El Tomato

nie jest to obsługiwane w iOS 11 Swift 4
— Boris Nikolic

30

W tym celu przydatne może być rozszerzenie w Swift.

Swift 4 i Swift 5:

Szybkie rozszerzenie (np. W pliku UITableViewExtension.swift):

import UIKit

extension UITableView {

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

}

Użyj np .:

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

    self.tableView.deselectSelectedRow(animated: true)
}

1
Moim zdaniem ta odpowiedź jest lepsza, ponieważ umieszczenie pustki w viewWillAppear()metodzie pomaga użytkownikowi zrozumieć, skąd wraca.
— MonsieurDart

idealny w razie potrzeby
— Patel Jigar,

28

Sprawdź, czy metoda delegowania jest poprawna, czy nie. Na przykład;

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

dla

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

Przez cały czas dzwoniłem do niewłaściwej metody! Dziękuję Ci!
— Damir Kotoric

1
o rany .... krwawa autouzupełnianie !!! Rozpracowanie tego zajęło mi kilka godzin !!! OMG ... Chcę cię pocałować!
— George Asda,


16

To rozwiązanie dla Swift 4

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

poprostu dodaj

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

To działa jak urok

przykład:

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

dopóki nie dodasz zaznaczenia podczas edycji w widoku tabeli, nie będzie możliwe wybranie żadnej komórki, ponieważ odznaczy ją po
— zakończeniu

Z pewnością jest to właściwe podejście, kiedy nie jesteś edycji, kiedy jesteś „tapping rząd do zrobienia czegoś”
— fattie

11

Oprócz ustawienia komórki jako wybranej, musisz również poinformować tableView, że komórka jest wybrana. Dodaj wywołanie do -tableView:selectRowAtIndexPath:animated:scrollPosition:swojej willDisplayCell:metody: będziesz mógł odznaczyć ją jak zwykle.

- (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];   
    } 
}

Pamiętaj, aby użyć UITableViewScrollPositionNone, aby uniknąć dziwnego przewijania.


1
Absolutnie poprawne. Myślę, że [cell setSelected:YES]można to pominąć: selectRowAtIndexPathzajmie się selectedstanem komórki
— spas

Ta odpowiedź działa w przypadku UITableView z wieloma opcjami wyboru. Kciuki w górę.
— Danny Bravo

6

To powinno działać:

[tableView deselectRowAtIndexPath:indexpath1 animated:NO];

Upewnij się tylko, że materialTable i tableView wskazują na ten sam obiekt.

Czy materiały są podłączone do tableView w Konstruktorze interfejsów?


testowałem z NIE, ale to również nie rozwiązało mojego problemu. ale naprawiłem ten problem w inny sposób jako przeładowane dane, gdy tylko delegat didselect został zwolniony.
— Ram

6

W oparciu o rozwiązanie saikirans napisałem to, co mi pomogło. W pliku .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];

}

I w pliku nagłówkowym:

@property (retain, nonatomic) NSIndexPath* selectedRowIndex;

Nie mam zbyt dużego doświadczenia, więc sprawdź dwukrotnie, czy nie ma wycieków pamięci itp.


6

Jeśli chcesz zaznaczyć dowolną komórkę tabeli za pomocą pierwszego kliknięcia i odznaczyć za pomocą drugiego, powinieneś użyć tego kodu:

- (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

Swift 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
self.tableView(tableView, didDeselectRowAt: indexPath)tableView.deselectRow...
— Działa


3

Spróbuj tego

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

spróbuj wyjaśnić swoją odpowiedź, w przeciwnym razie powinien to być komentarz.
— Hugo Dozois

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

umieść ten kod zgodnie z kodem, a komórka zostanie odznaczona.


3

Czy możesz tego spróbować?

- (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];
    }
}

To zadziałało dla mnie.


2

Swift 3.0:

Zgodnie z sekcją dotyczącą zgodności protokołu przewodnika po stylu ray wenderlich swift , aby zgrupować powiązane metody, umieść to rozszerzenie poniżej klasy kontrolera widoku w następujący sposób:

// 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

Szybki

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

Szybki 3

Natknąłem się również na to - kiedy nawigujesz lub odsuwasz się z powrotem do widoku tabeli, zwykle nie usuwa zaznaczenia wcześniej wybranego wiersza. Umieszczam ten kod w kontrolerze widoku tabeli i działa dobrze:

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

1

Szybki 3/4

W ViewController:

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

W komórce niestandardowej:

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


0

Aby usunąć zaznaczenie (DidDeselectRowAt), uruchamiane przy pierwszym kliknięciu z powodu wstępnie załadowanych danych; musisz poinformować tableView, że wiersz jest już zaznaczony, aby rozpocząć, więc pierwsze kliknięcie usuwa zaznaczenie wiersza:

// 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

Odkryłem, że oprócz ustawiania komórki jako wybranej , musisz poinformować widok tabeli, aby wybrać wiersz przy danej ścieżce indeksu.

// 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)
    }
}
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.