-didSelectRowAtIndexPath: nie jest wywoływany


295

Piszę aplikację na iOS z widokiem tabeli w widoku karty. W moim przypadku UITableViewControllerzaimplementowałem -tableView:didSelectRowAtIndexPath:, ale kiedy wybieram wiersz w czasie wykonywania, metoda nie jest wywoływana. Widok tabeli jest jednak zapełniany, więc wiem, że wywoływane są inne metody tableView w moim kontrolerze.

Czy ktoś ma jakieś pomysły, co spieprzyłem, aby tak się stało?


79
również możesz mieć gestRecognizer na UITableView, który absorbuje zaznaczenie .. (jedna z możliwości)
M.Othman

Uważaj, jeśli widok tabeli jest zapełniany, oznacza to, że DataSource jest dobrze ustawiony. Wybór jest częścią metod delegowania. Więc może DataSource jest dobrze ustawiony, ale nie Delegat!
Thomas Besnehard

1
Cześć M.Othman, twój komentarz jest dokładnie tym, co było nie tak z moim problemem. Czy wiesz, jak sprawić, by gestRecognizer działał „z” UITableView?
yhl

15
Zauważam, że jeśli stuknę i przytrzymam, stuknięcie ostatecznie zadzwoni -didSelectRowAtIndexPath. Zrozumiałem czapkę, ponieważ mam widok rozpoznawania gestów w widoku stołu i gest musi zawieść najpierw przed dotknięciem. Rozpoznawanie gestów nie wpływa na animację wyboru stołu.
Hlung

6
Miałem tutaj ten sam problem i miałem szczęście dowiedzieć się, że nie można wykonać gestu Recognizer na UITableView. Dzięki M. Othman!
vnchopra

Odpowiedzi:


97

Wygląda na to, że klasa nie jest odpowiednia UITableViewDelegatedo tego widoku tabeli, choć UITableViewControllerpowinna to ustawić automatycznie.

Czy jest jakaś szansa, że ​​przywrócisz delegata do innej klasy?


7
Odkryłem, że chociaż mój kontroler był UITableViewController, użyłem zwykłego starego widżetu UIViewController w UI Builder. To nie działa. Kiedy usunąłem widget UIViewController i upuściłem UITableViewController na jego miejscu, wszystko działało.
Matt Pfefferle,

1
Kolejna sprawa graniczna dla wszystkich - podłączyłem delegata kodem i zapomniałem, że wcześniej podłączyłem delegata za pośrednictwem scenorysu ... ostatni, aby go ustawić, wygrywa.
Oliver Dungey,

1
czy możesz pokazać, jak „zresetować delegata do innej klasy”? Mam ten sam problem i nie mogę go rozwiązać
Alfro,

1
myTableViewController.tableView.delegate = xxx
Hunter

534

Na wypadek, gdyby ktoś popełnił ten sam głupi błąd, co ja:

Sprawdź, czy nazwa metody, której się spodziewasz, didSelectmoże zostać przypadkowo uzyskana didDeselect. Dowiedziałem się około dwóch godzin ...


47
Ten sam problem tutaj. Jest tak, ponieważ XCode automatycznie uzupełnia Odznacz przed Wybierz.
user1021430

Podobnie, ustawiłem parametr allowSelection = false, który oprócz usunięcia podświetlenia zaznaczenia zapobiega również naciskaniu komórki!
djinne95

503

Inną rzeczą, która może prowadzić do problemu, jest nie wybrany rodzaj wyboru:

Rodzaj wyboru UITableView

Powinien być Single Selectiondo normalnego wyboru, nie powinien być No Selection.

Aby to zrobić programowo, wykonaj:

tableView.allowsSelection = YES

4
Ciągle się na to natrafiam, ponieważ mam sceny, które są zawsze w trybie edycji i ciągle zapominam o zmianie domyślnej z „Brak wyboru podczas edycji”.
Symetryczny

3
Możesz dodać ten wiersz w metodzie -viewDidLoad metody viewControlller NSParameterAssert (self.tableView.allowsSelection);
Nikolay Shubenkov

dla tych, którzy obserwowali tableView.rx.itemSelected.subscribe nie oddzwonili, to jest problem i powyższe poprawki działają
Dhilip

tak pomocne, gdy przejmujesz bazę kodu i ma ona kod za pomocą przycisków z tagami, a nie didSelectRow, z tym zaznaczeniem wyłączonym w serii ujęć 🙄
Nitin Alabur 30.01.2019

czy to zachowanie tableView jest domyślne?
Frostmourne

296

Inną możliwością jest to, że UITapGestureRecognizer może jeść wydarzenia, jak miało to miejsce tutaj: https://stackoverflow.com/a/9248827/214070

Nie podejrzewałem tej przyczyny, ponieważ komórki tabeli nadal podświetlałyby się na niebiesko, jakby krany się przedostawały.


To był mój problem! Dziękuję bardzo!! Mam na myśli, że wcześniej działał wyraźnie, ale przestał działać po tym, jak zaimplementowałem UITapGestureRecognizer * tap = [[UITapGestureRecognizer przydziel]] initWithTarget: self action: @selector (dismissKeyboard)]; [self.view addGestureRecognizer: dotknij];
coolcool1994

26
Miałem ten sam problem, co Ty zaimplementowałeś właśnie @ coolcool1994 [dotknij setCancelsTouchesInView: NO]; i rozwiązałem problem.
nizx

Dziękuję, to mi pomaga. W moim przypadku didSelectRowAtIndexPathnie działa tylko po usunięciu komórki w commitEditingStyle. Następnie robię UITapGestureRecognizeri tapAction:dostał indexPathod sender.view( [self.tableView indexPathForCell:sender.view]) i wywołanie[self.tableView.delegate didSelectRowAtIndexPath:myIndexPath]
Alexmelyon

1
To też był mój problem. Dodaj kod, aby usunąć tapesture w widoku tabeli i działało to jak urok - (UITableViewCell *) tableView: (UITableView *) tableView cellForRowAtIndexPath: (NSIndexPath *) indexPath {UITapGestureRecognizer * gest = [[UITapGestureRecognizer ] w tym]; gest.cancelsTouchesInView = NO; [self.tableView addGestureRecognizer: gest]; }
Udaya Sri

6
Dzięki @nizx, w szybkim 4 tap.cancelsTouchesInView = false
Ariven Nadar

150

Wszystkie dobre odpowiedzi, ale jest jeszcze jedna rzecz, na którą należy zwrócić uwagę ...

(W szczególności przy programowym tworzeniu UITableView)

Upewnij się, że tableView może zareagować na wybór, ustawiając [tableView setAllowsSelection:YES];lub usuwając linię, która go ustawia NO.


9
Dodałbym setAllowsSelectionDuringEditing:do listy (gdy widok tabeli jest w trybie edycji)
alex-i

Dziękuję Ci! W IB musiałem zmienić wartość w sekcji „Wybór” na Single Selection.
Sasho,

90

Jeśli pojawi się problem, UITapGestureRecognizermożesz to naprawić:

  • w Storyboard:

wprowadź opis zdjęcia tutaj

w kodzie z Objective-C:

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

[tap setCancelsTouchesInView:NO];

w kodzie z Swift:

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

tap.cancelsTouchesInView = false

67

W takich sytuacjach spotkałem dwie rzeczy.

  1. Możliwe, że zapomniałeś wdrożyć protokół UITableViewDelegate lub nie ma punktu delegacji między klasą a widokiem tabeli.

  2. Możesz mieć UIView w swoim rzędzie, który jest pierwszym respondentem i zabiera kliknięcia. Powiedz przycisk UIB lub coś podobnego.


5
Zaczęło się to dziać na iOS 7, wyłączenie „Interakcja użytkownika włączona” widoków w contentView rozwiązało to.
Kof

1
@ Kof przybił go. Utworzenie UITableViewCell w kreatorze interfejsu Xcode 5 tworzy go z włączoną interakcją użytkownika = TAK. Zły Xcode 5!
jsd 10.10.2013

44

Miałem ten sam problem. I trudno było znaleźć. Ale gdzieś w moim kodzie było to:

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

Musi być return indexPath, inaczej -tableView:didSelectRowAtIndexPath:nie zostanie powołany.


2
dla did SelectRow At IndexPath poprawny podpis to: - (void) tableView: (UITableView *) tableView didSelectRowAtIndexPath: (NSIndexPath *) indexPath {
coolcool1994

Dla mnie nie zacząłbym wywoływać tableView: didSelectRowAtIndexPath, dopóki nie usunę całkowicie
willSelectRowAtIndexPath

38

Jeśli dodałeś gestRecognizer na UITableView, didSelectRowAtIndexPath nie zostanie wywołany.

Musisz więc użyć metody delegowania gestRecognizer, aby uniknąć dotyku w określonym widoku.

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {
    if ([touch.view isDescendantOfView:YourTable]) {
        return NO;
    }
    return YES;
}

3
if ([touch.view isDescendantOfView:YourTable])
Sudheesh,

29

Wystąpił problem polegający na tym, że po miesiącach nie patrzenia na mój kod zapomniałem, że wdrożyłem następującą metodę z powodu niektórych wymagań, które nie były konieczne

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

Aby wiersz został wybrany, powinien zwracać TAK.


24

MUSISZ wybrać te opcje

wprowadź opis zdjęcia tutaj

ale jeśli chcesz, aby UITableViewkliknięcie nie było podświetlane, powinieneś wprowadzić zmiany we UITableViewCellwłaściwościach.

Wybierz opcję Brak dla opcji Wybór, tak jak poniżej

wprowadź opis zdjęcia tutaj


20

Położyłem UITapGestureRecognizerwidok na stole, aby zwolnić klawiaturę, która uniemożliwiła didSelectRowAtIndexPath:wywołanie. Mam nadzieję, że to komuś pomoże.



19

Miałem ten sam problem

Powodem było użycie UITapGestureRecognizer. Chciałem zamknąć klawiaturę, kiedy stuknąłem gdziekolwiek indziej. Uświadomiłem sobie, że to nadpisuje wszystkie akcje z kranu, dlategodidSelectRowAtIndexPath funkcja nie została wywołana.

Kiedy komentuję powiązane wiersze UITapGestureRecognizer, działa. Ponadto możesz sprawdzić, UITapGestureRecognizer selectorczy podsłuch jest wciśnięty, UITableViewCellczy nie.


14

W moim przypadku, didSelctRowAtIndexPath niestawienie wynika, że wybrano żadnego w Doboru własności Tableview, zestaw do pojedynczego wyboru rozwiązać mój problem

wprowadź opis zdjęcia tutaj


11

Dla Xcode 6.4, Swift 1.2. „Tag” wyboru został zmieniony w IB. Nie wiem jak i dlaczego. Ustawienie go na „Pojedynczy wybór” sprawiło, że moje komórki widoku tabeli można ponownie wybrać. wprowadź opis zdjęcia tutaj


10

Mimo że inna odpowiedź została zaakceptowana, dodam jeszcze jeden możliwy problem i rozwiązanie dla osób, które zauważą ten problem:

Jeśli masz włączone automatyczne zliczanie referencji (ARC), może się okazać, że nawet po przypisaniu kontrolera jako delegata widoku, wiadomości widoku do kontrolera nie są odbierane, ponieważ ARC usuwa kontroler. Najwyraźniej wskaźnik delegowania UITableView nie jest liczony jako odwołanie do ARC, więc jeśli jest to jedyne odniesienie, kontroler zostanie zwolniony. Możesz sprawdzić, czy tak się dzieje, implementując metodę dealloc na kontrolerze i ustawiając tam punkt przerwania lub wywołanie NSLog.

Rozwiązaniem jest śledzenie kontrolera z silnym odniesieniem w innym miejscu, dopóki nie będziesz pewien, że już go nie potrzebujesz.


Kontroler jest zbierany, gdy jego widok jest nadal wyświetlany? Czy to może się zdarzyć?
Drux

@Drux Tak! Kiedy mi się to przydarzyło, była to prawie pierwsza wersja Obj-C z funkcją odśmiecania używaną na iOS i szczerze mówiąc, nie spisali się zbyt dobrze. Wiele odniesień było wyraźnie lub pośrednio „słabych”, które, IMO, powinny były być mocne. Doprowadziło to do dziwności, takich jak wyrzucanie elementów bezużytecznych obiektów w aktywnym użyciu przez warstwę wyświetlania. Od jakiegoś czasu nie pracowałem na iOS, więc nie mam pojęcia, czy nadal tak się dzieje w najnowszej wersji.
Andrew Gorcester,

Mój kod ma coraz większy problem z pamięcią i naprawiłem go trochę i gdzieś indziej w kodzie tuż po tym, jak didSelect nie zostanie wywołany tylko za pierwszym razem. Nie wiem, czy to uzasadnia problem, czy nie.
Amber K

10

Pamiętaj, aby ustawić źródło danych i delegować w metodzie viewDidLoad w następujący sposób:

[self.tableView setDelegate:self];

[self.tableView setDataSource:self];

Dzwoniłem do źródła danych, ale nie delegowałem ... dzięki!
Gmeister4

9

Moim problemem nie był żaden z powyższych. I taki kiepski. Ale pomyślałem, że wymienię to tutaj, na wypadek, gdyby komuś to pomogło.

Mam tableViewControllerkontroler „podstawowy”, a następnie tworzę podklasy tego kontrolera. Cały mój kod zapisywałem tableView:didSelectRowAtIndexPathrutynowo w klasie „podstawowej”. Całkowicie zapominając, że domyślnie ta procedura również została stworzona (choć bez kodu, który nic nie zrobiłby) we wszystkich moich podklasach. Więc kiedy uruchomiłem moją aplikację, uruchomiłem wersję podklasy kodu, nic nie zrobiłem i zasmuciło mnie. Więc oczywiście, kiedy usunąłem procedurę z podklas, użyłem procedury klasy mt „base” i jestem w biznesie.

Wiem. Nie śmiej się Ale może to uratuje kogoś straconą godzinę ...


8

Dając za to moje 2 centy.

Miałem niestandardowe UITableViewCell i był przycisk pokrywający całą komórkę, więc kiedy nastąpił dotyk, przycisk został wybrany, a nie komórka.

Albo usuń przycisk, albo w moim przypadku ustawiłem opcję Włącz interakcję użytkownika na wartość false, w ten sposób wybrana została komórka.


8

Jeśli to przeczytasz, nadal nie rozwiążesz problemu.

Mam komórkę niestandardową , w której pole wyboru „ Interakcja użytkownika włączona ” było wyłączone. Więc po prostu go włączam. Powodzenia.


7

Właśnie to miałem i jak mi się przydarzyło w przeszłości, to nie działało, ponieważ nie zwracałem uwagi na autouzupełnianie podczas próby dodania metody, a tak naprawdę kończę na implementacji tableView:didDeselectRowAtIndexPath: zamiast tableView:didSelectRowAtIndexPath:.


7

Upewnij się, że został wdrożony tableView:didSelectRowAtIndexPath a nietableView:didDeSelectRowAtIndexPath

Dostałem to więcej niż kilka razy !!


5

Wiem, że jest stary i problem został rozwiązany, ale miał podobny problem, myślałem, że problem dotyczy mojego niestandardowego UITableViewCell, ale rozwiązanie było zupełnie inne - ponownie uruchamiam XCode :), a następnie działa dobrze! prawie jak Windows :)


5

Jeśli widok tabeli jest w trybie edycji (np. [tableView setEditing:YES animated:NO];), Musisz ustawićtableView.allowsSelectionDuringEditing = YES;


4

Kolejny błąd, który mogłeś popełnić (tak jak ja): jeśli ustawisz segue w komórce, didSelectRowAtIndexPathnie jest wywoływany. Zamiast tego powinieneś ustawić swoje sekwencje na kontrolerze widoku.


4

Żadna z tych odpowiedzi nie działała dla mnie. Po około godzinie wymyśliłem coś bardzo podstępnego:

Mam widok tabeli wewnątrz komórki innego widoku tabeli. Postanowiłem zrobić widok obejmujący między innymi widok wewnętrznego stołu. Nazwałem ten widok contentView i podłączyłem go do xib.

Okazuje się, że UITableViewCell ma już contentView i robi z nim dziwne rzeczy. Problem rozwiązał się, gdy zmieniłem nazwę właściwości na mainContentView i ponownie podłączyłem widok do tej właściwości o zmienionej nazwie.


4

W moim przypadku, dynamicznie obliczyć wysokość TableView„s SuperVieww czasie ładowania. Z powodu błędnej kalkulacji TableViewzostał umieszczony poza SuperView. TableViewZostał sporządzony grzywny, jednak wszystko interakcja była wyłączona (i didSelectRowAtIndexPathnigdy nie został powołany). Bardzo trudny do wykrycia, ponieważ nie ma wizualnego wskazania, że TableViewnie jest „dostępny”.


4

W moim przypadku problem polegał na tym, że miałem UITableViewCellpodklasę i zaimplementowałem dwie metody: touchesBegan:withEvent:i touchesEnded:withEventobsługiwać fantazyjną animację dotykową. Ale zapomniałem dodać [super touchesBegan:touches withEvent:event];reklamę metody, [super touchesEnded:touches withEvent:event];aby poinformować również rodzica komórki o dotyku.

Tak więc zmiana kodu na następujący rozwiązała mój 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
}

1
Potwierdzam, że spowodowało to w szczególności problem OP
Josh Wolff

4

W moim przypadku rozwiązaniem była zmiana NIE na TAK w poniższej funkcji.

iOS 9+

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

To też był mój problem. Mam wiele implementacji tableView i zapomniałem rozdzielić dwa tableViews w tej metodzie.
przetestowane w turing
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.