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.