Wie hebe ich die Auswahl einer ausgewählten UITableView-Zelle auf?


212

Ich arbeite an einem Projekt, bei dem ich eine bestimmte Zelle vorwählen muss.

Ich kann eine Zelle mit auswählen -willDisplayCell, aber ich kann sie nicht abwählen, wenn der Benutzer auf eine andere Zelle klickt.

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

Kannst du helfen?


11
Diese Frage muss akzeptiert werden
Titouan de Bailleul

Antworten:


407

Verwenden Sie diesen Code

- (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
Es gibt einen didDeselectRowAtIndexPath, mit dem die Auswahl des vorherigen deaktiviert werden kann.
Huggie

3
Ich denke gerne, dass ich diesen Beitrag nicht positiv bewerten kann, da er einen ganzzahligen Überlauf verursachen würde :)
Milo

Hallo @ram, müssen Sie eine Antwort auf diese Frage auswählen
Fattie

4
Ich verstehe nicht ... dieser Code lässt niemals zu, dass etwas ausgewählt wird.
C. Tewalt

@matrixugly ist richtig. Es ist besser, dies im Inneren zu tun willSelectRowAt:. Eine vollständigere Antwort finden Sie hier: stackoverflow.com/questions/12693402/…
HuaTham

117

Verwenden Sie die folgende Methode in den Delegaten der Tabellenansicht didSelectRowAtIndexpath(oder von überall).

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

2
Es ist erwähnenswert, dass dies indexPathForSelectedRoweine Methode und keine Eigenschaft ist.
FreeAsInBeer

Süss! Wusste nichts davon [myTable indexPathForSelectedRow]. Ich habe mich vorher durch die Zellen geschlungen. Vielen Dank!
Guptron

@FreeAsInBeer Ist diese Unterscheidung irgendwie wichtig? Eigenschaftszugriffsmethoden sind Methoden.
devios1

@chaiguy Das ist in Ordnung, wenn es Ihnen nichts ausmacht, wenn Ihre Kollegen Sie für böse halten .
FreeAsInBeer

1
@ Supertecnoboff Es gibt keinen Unterschied in der Leistung zwischen den beiden Varianten.
FreeAsInBeer

38

Versuche dies:

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

1
Gute Arbeit ... Ich denke, 'Index' in der 2. Zeile sollte indexPath
El Tomato

Dies wird nicht unterstützt unter iOS 11 Swift 4
Boris Nikolic

30

Es kann nützlich sein, hierfür eine Erweiterung in Swift zu erstellen.

Swift 4 und Swift 5:

Schnelle Erweiterung (z. B. in einer UITableViewExtension.swift-Datei):

import UIKit

extension UITableView {

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

}

Verwenden Sie zB:

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

    self.tableView.deselectSelectedRow(animated: true)
}

1
Meiner Meinung nach ist diese Antwort besser, da das Einfügen der Verwüstung in die viewWillAppear()Methode dem Benutzer hilft, zu verstehen, woher er zurückkommt.
MonsieurDart

das perfekte wie ich brauchte
Patel Jigar

28

Bitte überprüfen Sie mit der Delegate-Methode, ob sie korrekt ist oder nicht. Beispielsweise;

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

zum

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

Ich habe die ganze Zeit die falsche Methode aufgerufen, arghh !! Danke dir!
Damir Kotoric

1
oh man .... verdammte Autovervollständigung !!! Ich habe mehrere Stunden gebraucht, um es herauszufinden !!! OMG ... ich will dich küssen!
George Asda

22

Swift 4:

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

Muss nicht als nicht optional deklariert werden, aber das ist richtig.
Michael

16

Dies ist eine Lösung für Swift 4

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

einfach hinzufügen

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

es wirkt wie ein Zauber

Beispiel:

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

Bis Sie beim Bearbeiten in Ihrer Tabellenansicht eine Auswahl hinzufügen, ist es unmöglich, eine Zelle auszuwählen, da diese nach Abschluss der Auswahl abgewählt wird :)
Mehdi Chennoufi

Dies ist sicherlich der richtige Ansatz, wenn Sie nicht bearbeiten, wenn Sie "auf eine Zeile tippen, um etwas zu tun"
Fattie

11

Zusätzlich zum Festlegen der Zelle als ausgewählt müssen Sie der tableView mitteilen, dass die Zelle ausgewählt ist. Fügen Sie -tableView:selectRowAtIndexPath:animated:scrollPosition:Ihrer willDisplayCell:Methode einen Aufruf hinzu : und Sie können die Auswahl wie gewohnt aufheben.

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

Stellen Sie sicher, dass Sie UITableViewScrollPositionNone verwenden, um ein ungewöhnliches Bildlaufverhalten zu vermeiden.


1
Absolut korrekt. Ich denke, das [cell setSelected:YES]könnte weggelassen werden: selectRowAtIndexPathkümmert sich um den selectedZustand der Zelle
Spassas

Diese Antwort funktioniert für UITableViews mit Mehrfachauswahl. Daumen hoch.
Danny Bravo

6

Das sollte funktionieren:

[tableView deselectRowAtIndexPath:indexpath1 animated:NO];

Stellen Sie einfach sicher, dass materialTable und tableView auf dasselbe Objekt zeigen.

Sind Materialien mit der tableView in Interface Builder verbunden?


Ich habe mit NEIN getestet, aber das löst mein Problem auch nicht. Aber ich habe dieses Problem auf eine andere Weise behoben, als Daten neu geladen wurden, wenn der Didselect-Delegierte jemals gefeuert hat.
Ram

6

Basierend auf der Saikirans-Lösung habe ich dies geschrieben, was mir geholfen hat. In der .m-Datei:

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

}

Und in der Header-Datei:

@property (retain, nonatomic) NSIndexPath* selectedRowIndex;

Ich bin auch nicht sehr erfahren, also überprüfe es noch einmal auf Speicherlecks usw.


6

Wenn Sie mit dem ersten Klick eine Tabellenzelle auswählen und mit dem zweiten abwählen möchten, sollten Sie diesen Code verwenden:

- (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
Dieser arbeitete für mich in Swift 3. Gerade hatte hinzuzufügen self.tableView(tableView, didDeselectRowAt: indexPath)nach , tableView.deselectRow...weil sie nicht automatisch aufgerufen wurde
elysch

4

Swift 2.0:

tableView.deselectRowAtIndexPath(indexPath, animated: true)

3

Versuche dies

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

Versuchen Sie, Ihre Antwort zu erklären, sonst sollte es ein Kommentar sein.
Hugo Dozois

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

Platzieren Sie diesen Code entsprechend Ihrem Code und Sie werden Ihre Zelle abgewählt.


3

Kannst du das versuchen?

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

Es hat bei mir funktioniert.


2

Swift 3.0:

Um die entsprechenden Methoden in Gruppen zu halten, folgen Sie dem Abschnitt zur Protokollkonformität des Ray Wenderlich Swift Style Guide , und fügen Sie diese Erweiterung wie folgt unter Ihre View Controller-Klasse ein:

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

Schnell

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

Swift 3

Ich bin auch darauf gestoßen - wenn Sie zur Tabellenansicht navigieren oder zurückspulen, wird die zuvor ausgewählte Zeile normalerweise nicht für Sie abgewählt. Ich habe diesen Code in den Table View Controller eingefügt und er funktioniert gut:

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

1

Swift 3/4

In ViewController:

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

In der benutzerdefinierten Zelle:

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


0

Deaktivieren der Auswahl (DidDeselectRowAt) beim ersten Klicken aufgrund vorinstallierter Daten; Sie müssen die tableView darüber informieren, dass die Zeile bereits ausgewählt ist, damit durch einen ersten Klick die Auswahl der Zeile aufgehoben wird:

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

Ich habe festgestellt, dass Sie zusätzlich zum Festlegen der ausgewählten Zelle die Tabellenansicht informieren müssen, um die Zeile am angegebenen Indexpfad auszuwählen .

// 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)
    }
}
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.