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?

Baran
źródło
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)
}
Saikiran K.
źródło
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];
Shamitha
źródło
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];
}
ikosdroid
źródło
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)
}
Thomas Neuteboom
źródło
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
jfalexvijay
źródło
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,
22

Swift 4:

tableView.deselectRow(at: indexPath, animated: true)
Andrea.Ferrando
źródło
Nie musi być uznany za opcjonalny, ale jest to poprawne.
Michael
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
}
tBug
źródło
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.

Drew C
źródło
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?

Jordania
źródło
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.

Yunus Nedim Mehel
źródło
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;
    }
}
CHiP-love-NY
źródło
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
    }
}
Serguei Vinnitskii
źródło
2
self.tableView(tableView, didDeselectRowAt: indexPath)tableView.deselectRow...
Działa
4

Swift 2.0:

tableView.deselectRowAtIndexPath(indexPath, animated: true)
Anit Kumar
źródło
3

Spróbuj tego

[self.tableView deselectRowAtIndexPath:[self.tableView indexPathForSelectedRow] animated:YES];
EnasAZ
źródło
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.

rahulchona
źródło
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.

Dattatraya Anarase
źródło
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)
    }
}
ronatory
źródło
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)

}
Programer_saeed
źródło
1
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
    tableView.deselectRow(at: indexPath, animated: true)
}
Aayushi
źródło
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)
    }
}
Trev14
źródło
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
}
Sevy11
źródło
0

szybki 3.0

    tableView.deselectRow(at: indexPath, animated: true)
Marcelo Gracietti
źródło
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)

    }
}
Arkelyan
źródło
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)
    }
}
David Para
źródło