-didSelectRowAtIndexPath: wird nicht aufgerufen

295

Ich schreibe eine iOS-App mit einer Tabellenansicht in einer Registerkartenansicht. In meinem habe UITableViewControllerich implementiert -tableView:didSelectRowAtIndexPath:, aber wenn ich zur Laufzeit eine Zeile auswähle, wird die Methode nicht aufgerufen. Die Tabellenansicht wird jedoch gefüllt, sodass ich weiß, dass andere tableView-Methoden in meinem Controller aufgerufen werden.

Hat jemand irgendwelche Ideen, was ich vermasselt habe, um dies zu ermöglichen?

Matt Pfefferle
quelle
79
Möglicherweise haben Sie auch einen gestureRecognizer über der UITableView, der die Auswahl aufnimmt. (eine der Möglichkeiten)
M.Othman
Seien Sie vorsichtig, wenn die Tabellenansicht gefüllt wird. Dies bedeutet, dass die DataSource gut eingestellt ist. Die Auswahl ist Teil der Delegate-Methoden. Vielleicht ist die DataSource gut eingestellt, aber nicht der Delegierte!
Thomas Besnehard
1
Hallo M.Othman, Ihr Kommentar ist genau das, was mit meinem eigenen Problem falsch war. Wissen Sie, wie Sie gestureRecognizer dazu bringen, mit dem zu arbeiten UITableView?
Yhl
15
Ich bemerke, dass wenn ich tippe und halte, das Tippen schließlich ruft -didSelectRowAtIndexPath. Ich habe es herausgefunden, weil ich eine Tippgestenerkennung in der Tabellenansicht habe und die Geste zuerst fehlschlagen muss, bevor ich die Berührung erhalte. Obwohl es seltsam ist, wird die Tabellenauswahlanimation vom Gestenerkenner nicht beeinflusst.
Hlung
6
Ich hatte hier das gleiche Problem und hatte die glückliche Gelegenheit zu erfahren, dass Sie keinen gestureRecognizer über UITableView haben können. Danke M. Othman!
Vnchopra

Antworten:

97

Es hört sich so an, als ob die Klasse nicht UITableViewDelegatefür diese Tabellenansicht geeignet ist, obwohl dies UITableViewControllerautomatisch festgelegt werden soll.

Gibt es eine Chance, dass Sie den Delegierten auf eine andere Klasse zurücksetzen?

Hunter
quelle
7
Ich stellte fest, dass mein Controller zwar ein UITableViewController war, ich jedoch ein einfaches altes UIViewController-Widget in UI Builder verwendete. Das geht nicht Als ich das UIViewController-Widget löschte und an seiner Stelle einen UITableViewController ablegte, funktionierte alles.
Matt Pfefferle
1
Ein weiterer Grenzfall für alle - ich habe den Delegierten im Code verkabelt und vergessen, dass ich den Delegierten zuvor über das Storyboard verkabelt hatte ... der letzte, der ihn festlegt, gewinnt.
Oliver Dungey
1
Können Sie bitte zeigen, wie Sie einen Delegierten auf eine andere Klasse zurücksetzen können? Ich habe das gleiche Problem und kann es nicht lösen
Alfro
1
myTableViewController.tableView.delegate = xxx
Hunter
534

Nur für den Fall, dass jemand den gleichen dummen Fehler gemacht hat wie ich:

Überprüfen Sie, ob der Methodenname dessen, was Sie erwarten, didSelectversehentlich didDeselectauf irgendeine Weise abgerufen werden kann. Es dauerte ungefähr zwei Stunden, bis ich es herausgefunden hatte ...

Dschee
quelle
47
Gleiches Problem hier. Dies liegt daran, dass XCode die Auswahl vor der Auswahl automatisch vervollständigt.
user1021430
In ähnlicher Weise hatte ich allowSelection = false gesetzt, was nicht nur das Entfernen von Auswahlhighlights verhindert, sondern auch verhindert, dass die Zelle gedrückt wird!
djinne95
503

Eine andere Sache, die zu dem Problem führen könnte, ist nicht ausgewählte Auswahlart:

UITableView Auswahlart

Sollte Single Selectionfür die normale Auswahl sein, sollte nicht sein No Selection.

Um dies programmgesteuert zu tun, gehen Sie wie folgt vor:

tableView.allowsSelection = YES
Dennis Krut
quelle
4
Ich stoße immer wieder darauf, weil ich Szenen habe, die sich immer im Bearbeitungsmodus befinden, und ich vergesse immer wieder, die Standardeinstellung von "Keine Auswahl während der Bearbeitung" zu ändern.
Symmetrische
3
Sie können diese Zeile in Ihre -viewDidLoad-Methode von viewControlller NSParameterAssert (self.tableView.allowsSelection) einfügen.
Nikolay Shubenkov
Für diejenigen, die beobachtet haben, dass tableView.rx.itemSelected.subscribe nicht zurückgerufen hat, ist dies das Problem und die oben genannten Korrekturen funktionieren
Dhilip
So hilfreich, wenn Sie eine Codebasis übernehmen und Code mit Schaltflächen mit Tags und nicht mit didSelectRow verwendet wird. Diese Auswahl ist im Storyboard deaktiviert 🙄
Nitin Alabur
Ist dies das Standardverhalten von tableView?
Frostmourne
296

Eine andere Möglichkeit besteht darin, dass ein UITapGestureRecognizer die Ereignisse frisst, wie dies hier der Fall war: https://stackoverflow.com/a/9248827/214070

Ich habe diese Ursache nicht vermutet, da die Tabellenzellen immer noch blau hervorheben würden, als würden die Wasserhähne durchkommen.

Bugloaf
quelle
Das war mein Problem! Ich danke dir sehr!! Ich meine, es hat eindeutig schon früher funktioniert, aber es hat nicht mehr funktioniert, nachdem ich UITapGestureRecognizer implementiert habe. [self.view addGestureRecognizer: tippen];
coolcool1994
26
Ich hatte das gleiche Problem wie Sie @ coolcool1994 gerade implementiert [tippen Sie auf setCancelsTouchesInView: NO]; und löste das Problem.
Nizx
Danke, es hilft mir. In meinem Fall didSelectRowAtIndexPathfunktioniert das erst nach dem Löschen der Zelle in commitEditingStyle. Dann mache ich UITapGestureRecognizerund in tapAction:kam indexPathvon sender.view( [self.tableView indexPathForCell:sender.view]) und rufe an[self.tableView.delegate didSelectRowAtIndexPath:myIndexPath]
Alexmelyon
1
Dies war auch mein Problem. Fügen Sie Code hinzu, um die Tapgesture in der Tabellenansicht zu entfernen, und es funktionierte wie ein Zauber - (UITableViewCell *) tableView: (UITableView *) tableView cellForRowAtIndexPath: (NSIndexPath *) indexPath {UITapGestureRecognizer * gesture = [[UITapGesture ] drin]; gesture.cancelsTouchesInView = NO; [self.tableView addGestureRecognizer: Geste]; }
Udaya Sri
6
Vielen Dank @nizx, in schnell 4 tap.cancelsTouchesInView = false
Ariven Nadar
150

Alles gute Antworten, aber es gibt noch eine, auf die Sie achten müssen ...

(Insbesondere beim programmgesteuerten Erstellen einer UITableView)

Stellen Sie sicher, dass tableView auf die Auswahl reagieren kann, [tableView setAllowsSelection:YES];indem Sie eine Zeile festlegen oder entfernen, auf die sie festgelegt ist NO.

Old McStopher
quelle
9
Ich würde setAllowsSelectionDuringEditing:der Liste hinzufügen (wenn sich die Tabellenansicht im Bearbeitungsmodus befindet)
alex-i
Danke dir! In IB musste ich den Wert des Abschnitts "Auswahl" auf ändern Single Selection.
Sasho
90

Wenn das Problem mit UITapGestureRecognizerIhnen auftritt, können Sie dies beheben:

  • im Storyboard:

Geben Sie hier die Bildbeschreibung ein

im Code mit Objective-C:

UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(dismissKeyboard)]; 
[self.view addGestureRecognizer:tap];

[tap setCancelsTouchesInView:NO];

im Code mit Swift:

let tap = UITapGestureRecognizer(target: self, action:Selector("dismissKeyboard"))
view.addGestureRecognizer(tap)

tap.cancelsTouchesInView = false
Bartłomiej Semańczyk
quelle
67

Ich bin in diesen Situationen auf zwei Dinge gestoßen.

  1. Möglicherweise haben Sie vergessen, das UITableViewDelegate-Protokoll zu implementieren, oder es gibt keinen Delegierungsausgang zwischen Ihrer Klasse und Ihrer Tabellenansicht.

  2. Möglicherweise befindet sich in Ihrer Zeile eine UIView, die als Ersthelfer fungiert und Ihre Klicks entfernt. Sagen Sie einen UIButton oder ähnliches.

Gilm
quelle
5
Dies begann unter iOS 7, indem das Deaktivieren der Option "Benutzerinteraktion aktiviert" für Ansichten in contentView behoben wurde.
Kof
1
@Kof hat es genagelt. Wenn Sie eine UITableViewCell im Interface Builder von Xcode 5 erstellen, wird diese mit aktivierter Benutzerinteraktion = YES erstellt. Schlechter Xcode 5!
jsd
44

Ich hatte das gleiche Problem. Und es war schwer zu finden. Aber irgendwo in meinem Code war dies:

- (NSIndexPath *)tableView:(UITableView *)tableView willSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    return nil;
}

Es muss sein return indexPath, sonst -tableView:didSelectRowAtIndexPath:wird nicht gerufen.

JackPearse
quelle
2
Für did SelectRow At IndexPath lautet die korrekte Signatur: - (void) tableView: (UITableView *) tableView didSelectRowAtIndexPath: (NSIndexPath *) indexPath {
coolcool1994
Für mich würde es nicht anfangen, tableView: didSelectRowAtIndexPath aufzurufen, bis ich willSelectRowAtIndexPath vollständig gelöscht habe
etayluz
38

Wenn Sie über UITableView einen gestureRecognizer hinzugefügt haben, didSelectRowAtIndexPathwird dieser nicht aufgerufen.

Sie müssen daher die delegate-Methode gestureRecognizer verwenden, um Berührungen in bestimmten Ansichten zu vermeiden.

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {
    if ([touch.view isDescendantOfView:YourTable]) {
        return NO;
    }
    return YES;
}
Vinu David Jose
quelle
3
if ([touch.view isDescendantOfView:YourTable])
Sudheesh
29

Ich bin auf ein Problem gestoßen, bei dem ich nach Monaten, in denen ich meinen Code nicht angesehen habe, vergessen habe, dass ich die folgende Methode implementiert habe, da einige Anforderungen nicht erforderlich waren

- (BOOL)tableView:(UITableView *)tableView shouldHighlightRowAtIndexPath:(NSIndexPath  *)indexPath{
    return NO;
}

Für eine Zeile sollte JA zurückgegeben werden, damit sie ausgewählt wird.

cpt.neverm1nd
quelle
24

SIE MÜSSEN diese Optionen auswählen

Geben Sie hier die Bildbeschreibung ein

Wenn Sie UITableViewjedoch beim Klicken nicht hervorheben möchten, sollten Sie Änderungen an den UITableViewCellEigenschaften vornehmen .

Wählen Sie die Option Keine für die Auswahl wie unten

Geben Sie hier die Bildbeschreibung ein

Mohsin Qureshi
quelle
20

Ich hatte eine UITapGestureRecognizerauf meine Tischansicht gestellt, um die Tastatur zu schließen, die einen Anruf verhinderte didSelectRowAtIndexPath:. Hoffe es hilft jemandem.

Groot
quelle
19

Ich hatte das gleiche Problem,

Der Grund war die Verwendung von UITapGestureRecognizer. Ich wollte, dass die Tastatur geschlossen wird, wenn ich irgendwo anders tippe. Mir wurde klar, dass dies alle Tap-Aktionen überschreibt, weshalb die didSelectRowAtIndexPathFunktion nicht aufgerufen wurde.

Wenn ich die zugehörigen Zeilen kommentiere UITapGestureRecognizer, funktioniert es. Außerdem können Sie überprüfen, UITapGestureRecognizer selectorob das Abhören erfolgt UITableViewCelloder nicht.

Jeyhun Karimov
quelle
14

In meinem Fall ist didSelctRowAtIndexPath nicht aufrufend darauf zurückzuführen, dass ich in der Selection- Eigenschaft von tableView keine ausgewählt habe. Die Einstellung auf einzelne Auswahl hat mein Problem gelöst

Geben Sie hier die Bildbeschreibung ein

Naveed Ahmad
quelle
11

Für Xcode 6.4 Swift 1.2. Die Auswahl "Tag" wurde in IB geändert. Ich weiß nicht wie und warum. Durch Einstellen auf "Einzelauswahl" konnten meine Tabellenansichtszellen wieder ausgewählt werden. Geben Sie hier die Bildbeschreibung ein

MB_iOSDeveloper
quelle
10

Obwohl eine andere Antwort akzeptiert wurde, werde ich ein weiteres mögliches Problem und eine mögliche Lösung für Personen hinzufügen, die dieses Problem beobachten:

Wenn Sie die automatische Referenzzählung (ARC) aktiviert haben, werden Sie möglicherweise feststellen, dass die Nachrichten der Ansicht an die Steuerung auch nach dem Zuweisen Ihres Controllers als Delegat der Ansicht nicht empfangen werden, da ARC die Steuerung löscht. Anscheinend zählt der Delegatenzeiger von UITableView nicht als Referenz für den ARC. Wenn dies also der einzige Verweis darauf ist, wird der Controller freigegeben. Sie können überprüfen, ob dies geschieht, indem Sie die Dealloc-Methode auf dem Controller implementieren und dort einen Haltepunkt oder einen NSLog-Aufruf festlegen.

Die Lösung besteht darin, den Controller mit einer starken Referenz an einer anderen Stelle zu verfolgen, bis Sie sicher sind, dass Sie ihn nicht mehr benötigen.

Andrew Gorcester
quelle
Wird der Controller durch Müll gesammelt, während seine Ansicht noch angezeigt wird? Kann das tatsächlich passieren?
Drux
@Drux Ja! Als mir das passierte, war es fast die erste Version von Obj-C mit Garbage Collection, die unter iOS verwendet wurde, und ehrlich gesagt haben sie keine großartige Arbeit geleistet. Viele Referenzen waren explizit oder implizit "schwach", was, IMO, stark sein sollte. Dies führte zu Kuriositäten wie der Speicherbereinigung von Objekten, die von der Anzeigeebene aktiv verwendet werden. Ich habe seit einiger Zeit keine iOS-Arbeit mehr gemacht, daher habe ich keine Ahnung, ob dies in der neuesten Version noch passiert.
Andrew Gorcester
Mein Code hat ein wachsendes Problem mit der Speichergröße und ich habe etwas davon behoben und irgendwo anders im Code kurz danach wurde didSelect nicht nur beim ersten Mal aufgerufen. Ich weiß nicht, ob dies das Problem rechtfertigt oder nicht.
Amber K
10

Denken Sie daran, die Datenquelle festzulegen und in der viewDidLoad-Methode wie folgt zu delegieren:

[self.tableView setDelegate:self];

[self.tableView setDataSource:self];
Carlos
quelle
Ich habe die Datenquelle angerufen, aber nicht delegiert ... danke!
Gmeister4
9

Mein Problem war keines der oben genannten. Und so lahm. Aber ich dachte, ich würde es hier auflisten, falls es jemandem hilft.

Ich habe einen tableViewController, der mein "Basis" -Controller ist, und dann erstelle ich Unterklassen dieses Controllers. Ich habe meinen gesamten Code in der tableView:didSelectRowAtIndexPathRoutine in der "Basis" -Klasse geschrieben. Ganz zu vergessen, dass diese Routine standardmäßig auch in allen meinen Unterklassen erstellt wurde (allerdings ohne Code, der irgendetwas bewirkt hat). Als ich meine App ausführte, wurde die Unterklassenversion des Codes ausgeführt, nichts unternommen und ich wurde traurig. Nachdem ich die Routine aus den Unterklassen entfernt hatte, verwendete sie natürlich die Routine der mt-Basisklasse und ich bin im Geschäft.

Ich kenne. Lache nicht. Aber vielleicht spart das jemandem die Stunde, die ich verloren habe ...

Steve
quelle
8

Ich gebe meine 2 Cent dafür.

Ich hatte eine benutzerdefinierte UITableViewCell und es gab eine Schaltfläche, die die gesamte Zelle abdeckte. Als die Berührung erfolgte, wurde die Schaltfläche ausgewählt und nicht die Zelle.

Entfernen Sie entweder die Schaltfläche, oder in meinem Fall setze ich User Interation Enable auf der Schaltfläche auf false. Auf diese Weise wurde die Zelle ausgewählt.

gmogames
quelle
8

Wenn Sie dies lesen, löst sich das Problem immer noch nicht.

Ich habe eine benutzerdefinierte Zelle, in der das Kontrollkästchen " Benutzerinteraktion aktiviert " deaktiviert war. Also schalte ich es einfach ein. Viel Glück.

HotJard
quelle
7

Ich hatte das gerade und wie mir in der Vergangenheit passiert ist, hat es nicht funktioniert, weil ich beim Hinzufügen der Methode nicht auf die automatische Vervollständigung geachtet habe und am Ende tatsächlich implementiert habe tableView:didDeselectRowAtIndexPath: statt tableView:didSelectRowAtIndexPath:.

Benutzer486646
quelle
7

Stellen Sie sicher, dass Sie implementiert haben tableView:didSelectRowAtIndexPathund nichttableView:didDeSelectRowAtIndexPath

Das hat mich mehr als ein paar Mal erwischt !!

SleepsOnNewspapers
quelle
5

Ich weiß, ist alt und das Problem wurde behoben, aber ein ähnliches Problem hatte, ich dachte, dass das Problem mit meiner benutzerdefinierten UITableViewCell war, aber die Lösung war völlig anders - ich starte XCode neu :) und funktioniert dann ok! fast wie Windows :)

Lukasz
quelle
5

Wenn sich Ihre Tabellenansicht im Bearbeitungsmodus befindet (z. B. [tableView setEditing:YES animated:NO];), müssen Sie festlegentableView.allowsSelectionDuringEditing = YES;

yvetterowe
quelle
4

Ein weiterer Fehler, den Sie hätten machen können (wie ich): Wenn Sie in der Zelle einen Übergang festlegen, didSelectRowAtIndexPathwird dieser nicht aufgerufen. Sie sollten Ihre Segmente stattdessen am View Controller einstellen.

juanignaciosl
quelle
4

Keine dieser Antworten hat bei mir funktioniert. Nach ungefähr einer Stunde fand ich etwas sehr heimtückisches heraus:

Ich habe eine Tabellenansicht in einer Zelle einer anderen Tabellenansicht. Ich habe mich für eine umschließende Ansicht entschieden, die unter anderem die innere Tabellenansicht enthält. Ich habe diese Ansicht contentView aufgerufen und sie in die xib eingebunden.

Es stellt sich heraus, dass UITableViewCell bereits eine contentView hat und seltsame Dinge damit macht. Das Problem wurde von selbst behoben, als ich die Eigenschaft in mainContentView umbenannte und die Ansicht wieder mit dieser umbenannten Eigenschaft verband.

Xytor
quelle
4

In meinem Fall berechne ich dynamisch die Höhe des TableView‚s SuperViewzur Ladezeit. Aufgrund einer Fehleinschätzung wurde der TableViewaußerhalb des positioniert SuperView. Das TableViewwurde gut gezeichnet, jedoch war jede Interaktion deaktiviert (und didSelectRowAtIndexPathwurde nie aufgerufen). Sehr schwer zu erkennen, da es keinen visuellen Hinweis darauf gibt, dass der TableViewnicht "zugänglich" ist.

GK100
quelle
4

In meinem Fall war das Problem, dass ich eine UITableViewCellUnterklasse hatte und diese beiden Methoden implementiert hatte: touchesBegan:withEvent:& touchesEnded:withEventum eine ausgefallene Animation bei Berührung zu handhaben. Aber ich hatte vergessen, die [super touchesBegan:touches withEvent:event];Methodenanzeige hinzuzufügen[super touchesEnded:touches withEvent:event]; um auch die Eltern der Zelle über die Berührung zu informieren.

Das Ändern des Codes in Folgendes löste mein Problem:

-(void) touchesBegan:(NSSet*)touches withEvent:(UIEvent*)event{
    [super touchesBegan:touches withEvent:event];
    //blah blah blah
}

-(void) touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event{
    [super touchesEnded:touches withEvent:event];
    //rest of the code
}
alternatiph
quelle
1
Kann bestätigen, dass dies insbesondere für mich das Problem des OP verursacht hat
Josh Wolff
4

In meinem Fall bestand die Lösung darin, in der folgenden Funktion NEIN in JA zu ändern.

iOS 9+

- (BOOL)tableView:(UITableView *)tableView shouldHighlightRowAtIndexPath:(NSIndexPath *)indexPath
{
    return YES;
}
HonkyHonk
quelle
Das war auch mein Problem. Ich habe eine Implementierung mit mehreren tableView und habe vergessen, die beiden tableViews in dieser Methode zu trennen.
Turing getestet