-didSelectRowAtIndexPath: не вызывается


295

Я пишу приложение для iOS с табличным представлением внутри представления вкладок. По моему UITableViewController, я реализовал -tableView:didSelectRowAtIndexPath:, но когда я выбираю строку во время выполнения, метод не вызывается. Однако табличное представление заполняется, поэтому я знаю, что в моем контроллере вызываются другие методы tableView.

У кого-нибудь есть идеи, что я, возможно, облажался, чтобы это произошло?


79
также у вас может быть gestRecognizer поверх UITableView, который поглощает выделение .. (одна из возможностей)
M.Othman

Будьте осторожны, если табличное представление заполняется, это означает, что источник данных правильно настроен. Выбор является частью методов делегата. Так что, возможно, источник данных хорошо настроен, но не делегат!
Томас Беснехард

1
Привет, М. Отман, ваш комментарий - это именно то, что не так с моей собственной проблемой. Знаете ли вы, как заставить gestRecognizer работать «с» UITableView?
yhl

15
Я замечаю, что если я нажму и удерживаю, тап со временем звонит -didSelectRowAtIndexPath. Я разобрался с шляпой, потому что у меня есть распознаватель жестов касания на виде таблицы, и этот жест должен потерпеть неудачу прежде, чем получит касание. Хотя это странно, анимация выбора таблицы не зависит от распознавателя жестов.
Хлунг

6
У меня возникла та же проблема, и мне посчастливилось узнать, что у вас не может быть gestRecognizer поверх UITableView. Спасибо М. Осман!
vnchopra

Ответы:


97

Похоже, что класс не предназначен UITableViewDelegateдля этого табличного представления, хотя UITableViewControllerдолжен устанавливать его автоматически.

Есть ли шанс, что вы сбросите делегат в какой-то другой класс?


7
Я обнаружил, что, хотя моим контроллером был UITableViewController, я использовал обычный старый виджет UIViewController в UI Builder. Это не работает Когда я удалил виджет UIViewController и уронил UITableViewController на его место, все работало.
Мэтт Пфефферле

1
Еще один граничный случай для всех - я запрограммировал делегата в коде и забыл, что ранее он связывал делегата через раскадровку ... последний, который установил, побеждает.
Оливер Данджи,

1
Можете ли вы показать, как "сбросить делегат в другой класс", пожалуйста? У меня есть та же самая проблема, и я не могу решить ее
Альфро

1
myTableViewController.tableView.delegate = xxx
Охотник

534

На всякий случай кто-то сделал ту же самую глупую ошибку, что и я:

Проверьте, можно ли didSelectслучайно получить имя метода того, кем вы ожидаете быть didDeselect. Мне потребовалось около двух часов, чтобы выяснить ...


47
Та же проблема здесь. Это потому, что XCode автоматически завершает отмена выбора перед выбором.
user1021430

Точно так же я установил allowSelection = false, который, как и удаление выделения выделения, также предотвращает нажатие на ячейку!
djinne95

503

Еще одна вещь, которая может привести к проблеме, это не выбор вида:

UITableView выбор вида

Должно быть Single Selectionдля нормального выбора, не должно быть No Selection.

Чтобы сделать это программно, выполните:

tableView.allowsSelection = YES

4
Я продолжаю сталкиваться с этим, потому что у меня есть сцены, которые всегда находятся в режиме редактирования, и я забываю изменить значение по умолчанию «Нет выбора во время редактирования».
Симметричный

3
Вы можете добавить эту строку в свой метод -viewDidLoad viewControlller NSParameterAssert (self.tableView.allowsSelection);
Николай Шубенков

для тех, кто наблюдал, что tableView.rx.itemSelected.subscribe не перезванивал, это проблема, и выше исправление работает
Dhilip

так полезно, когда вы берете некоторую кодовую базу и она содержит код с использованием кнопок с тегами, а не didSelectRow, когда этот выбор отключен в раскадровке 🙄
Нитин Алабур

такое поведение tableView по умолчанию?
Ледяная Скорбь

296

Другая возможность состоит в том, что UITapGestureRecognizer может есть события, как здесь: https://stackoverflow.com/a/9248827/214070

Я не подозревал эту причину, потому что ячейки таблицы по-прежнему будут выделены синим цветом, как если бы краны проходили.


Это была моя проблема! Огромное спасибо!! Я имею в виду, что раньше он явно работал, но перестал работать после того, как я реализовал UITapGestureRecognizer * tap = [[UITapGestureRecognizer alloc] initWithTarget: self action: @selector (dismissKeyboard)]; [self.view addGestureRecognizer: нажмите];
coolcool1994

26
У меня была та же проблема, что вы @ coolcool1994 только что реализовали [нажмите setCancelsTouchesInView: NO]; и решил вопрос.
nizx

Спасибо, это помогает мне. В моем случае didSelectRowAtIndexPathне работает только после удаления ячейки в commitEditingStyle. Затем я делаю UITapGestureRecognizerи tapAction:получил получил indexPathот sender.view( [self.tableView indexPathForCell:sender.view]) и колл[self.tableView.delegate didSelectRowAtIndexPath:myIndexPath]
Alexmelyon

1
Это тоже была моя проблема ... добавить код для удаления указателя в табличном представлении, и это работало как талисман - (UITableViewCell *) tableView: (UITableView *) tableView cellForRowAtIndexPath: (NSIndexPath *) indexPath {UITapGestureRecognizer * жест = [[UITapGestureRecognec ] в этом]; жест.cancelsTouchesInView = NO; [self.tableView addGestureRecognizer: жест]; }
Удая Шри

6
Спасибо @nizx, в быстром 4 tap.cancelsTouchesInView = false
Аривен Надар

150

Все хорошие ответы, но есть еще один, чтобы высматривать ...

(Особенно при программном создании UITableView)

Убедитесь, что tableView может реагировать на выбор, устанавливая [tableView setAllowsSelection:YES];или удаляя любую строку, которая устанавливает его NO.


9
Я бы добавил setAllowsSelectionDuringEditing:в список (когда просмотр таблицы в режиме редактирования)
alex-i

Спасибо! В IB пришлось изменить значение в разделе «Выбор» на Single Selection.
Сашо

90

Если проблема возникает с UITapGestureRecognizerвами, вы можете исправить это:

  • в раскадровке:

введите описание изображения здесь

в коде с Objective-C:

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

[tap setCancelsTouchesInView:NO];

в коде с Swift:

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

tap.cancelsTouchesInView = false

67

Я столкнулся с двумя вещами в этой ситуации.

  1. Возможно, вы забыли реализовать протокол UITableViewDelegate, или нет выхода делегирования между вашим классом и табличным представлением.

  2. У вас может быть UIView внутри вашей строки, который является первым респондентом и убирает ваши клики. Скажите UIButton или что-то подобное.


5
Это начало происходить на iOS 7, это было исправлено отключением «Взаимодействие с пользователем» для представлений в contentView.
Kof

1
@ Коф прибил это. Создание UITableViewCell в конструкторе интерфейса Xcode 5 создает его с включенным взаимодействием с пользователем = YES. Плохой Xcode 5!
13

44

У меня была такая же проблема. И это было трудно найти. Но где-то в моем коде было это:

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

Должно быть return indexPath, иначе -tableView:didSelectRowAtIndexPath:не называется.


2
для did SelectRow в IndexPath правильная подпись: - (void) tableView: (UITableView *) tableView didSelectRowAtIndexPath: (NSIndexPath *) indexPath {
coolcool1994

Для меня это не начинало бы вызывать tableView: didSelectRowAtIndexPath, пока я полностью не удалил willSelectRowAtIndexPath
etayluz

38

Если вы добавили gestRecognizer поверх UITableView, didSelectRowAtIndexPathвызываться не будет.

Таким образом, вам нужно использовать метод делегата gestRecognizer, чтобы избежать касания в конкретном представлении.

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

3
if ([touch.view isDescendantOfView:YourTable])
Судхи

29

Я столкнулся с проблемой, когда после нескольких месяцев не глядя на мой код, я забыл, что реализовал следующий метод из-за некоторых требований, которые не были необходимы

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

Он должен возвращать YES для строки, чтобы сделать ее выбранной.


24

ВЫ ДОЛЖНЫ выбрать эти варианты

введите описание изображения здесь

но если вы хотите, чтобы UITableViewпри нажатии кнопки не выделялись, вам следует внести изменения в UITableViewCellсвойства.

Выберите «Нет» для выбора, как показано ниже

введите описание изображения здесь


20

Я положил UITapGestureRecognizerна свое табличное представление, чтобы отклонить клавиатуру, которая препятствовала тому, didSelectRowAtIndexPath:чтобы быть вызванным. Надеюсь, это кому-нибудь поможет.


19

Если у вас возникла та же проблема, что и у меня: очевидно, этот метод не будет вызываться, если ваш tableView находится в режиме редактирования. Вы должны установить для allowSelectionDuringEditing значение true.

С помощью этого вопроса: при редактировании `UITableView` не вызывает didSelectRowAtIndexPath ??


19

У меня такая же проблема,

Причиной было использование UITapGestureRecognizer. Я хотел, чтобы клавиатура отклонялась, когда я нажимал в другом месте. Я понял, что это отменяет все действия крана, поэтому didSelectRowAtIndexPathфункция не вызывается .

Когда я комментирую строки, связанные с UITapGestureRecognizer, это работает. Кроме того, вы можете проверить в функции, UITapGestureRecognizer selectorесли постучал UITableViewCellили нет.


14

В моем случае не вызывал didSelctRowAtIndexPath из-за того, что я не выбрал ни одного в свойстве Selection таблицы tableView, установка единственного выбора решила мою проблему

введите описание изображения здесь


11

Для Xcode 6.4, Swift 1.2. Выбор «тег» был изменен в IB. Я не знаю как и почему. Установка этого параметра на «Единый выбор» позволила снова выбрать ячейки моего табличного представления. введите описание изображения здесь


10

Несмотря на то, что был принят другой ответ, я добавлю еще одну возможную проблему и решение для людей, которые наблюдают за этой проблемой:

Если у вас включен автоматический подсчет ссылок (ARC), вы можете обнаружить, что даже после назначения контроллера в качестве делегата представления сообщения представления на контроллер не принимаются, поскольку ARC удаляет контроллер. Очевидно, указатель делегата UITableView не считается ссылкой для ARC, поэтому, если это единственная ссылка на него, контроллер будет освобожден. Вы можете проверить, происходит ли это, реализуя метод dealloc на контроллере и устанавливая точку останова или вызов NSLog там.

Решение состоит в том, чтобы отслеживать контроллер с сильной ссылкой где-то еще, пока вы не будете уверены, что он вам больше не понадобится.


Контроллер собирает мусор, пока его вид все еще отображается? Может ли это на самом деле произойти?
Друкс

@ Друкс Да! Когда это случилось со мной, это была почти первая версия Obj-C с сборкой мусора, используемой на iOS, и, честно говоря, они не сделали большую работу. Многие ссылки были явно или неявно «слабыми», что, IMO, должно было быть сильным. Что привело к странностям, таким как сборка мусора объектов, которые активно используются слоем отображения. Я давно не работал с iOS, поэтому понятия не имею, произойдет ли это в последней версии.
Эндрю Горчестер

Мой код имеет растущую проблему с размером памяти, и я исправил кое-что из этого и где-то еще в коде сразу после того, как thisSelect не будет вызываться только в первый раз. Я не знаю, оправдывает ли это проблему или нет.
Янтарь К

10

Не забудьте установить источник данных и делегировать в методе viewDidLoad следующим образом:

[self.tableView setDelegate:self];

[self.tableView setDataSource:self];

Я звонил в источник данных, но не делегировал ... спасибо!
Gmeister4

9

Моей проблемой не было ничего из вышеперечисленного. И так хромает. Но я думал, что перечислю это здесь на случай, если это кому-нибудь поможет.

У меня tableViewControllerесть «базовый» контроллер, а затем я создаю подклассы этого контроллера. Я писал весь свой код в tableView:didSelectRowAtIndexPathподпрограмме в «базовом» классе. Полностью забыв, что по умолчанию эта подпрограмма также была создана (хотя и без кода, который что-либо делал) во всех моих подклассах. Поэтому, когда я запустил свое приложение, оно запустило версию кода для подклассов, ничего не сделало и огорчило меня. Поэтому, разумеется, когда я удалил подпрограмму из подклассов, она использовала подпрограмму класса «mt», и я в деле.

Я знаю. Не смейся Но, возможно, это спасет кого-то за час, который я потерял ...


8

Давая мои 2 цента на это.

У меня был Custom UITableViewCell, и была кнопка, покрывающая всю ячейку, поэтому, когда произошло касание, была выбрана кнопка, а не ячейка.

Либо удалите кнопку, либо в моем случае я установил для кнопки «Интеграция пользователя» значение «ложь», чтобы была выбрана ячейка.


8

Если вы читаете это, значит, проблема не решена.

У меня есть пользовательская ячейка, где флажок « Взаимодействие с пользователем включено » был отключен. Итак, я просто включаю его. Удачи.


7

У меня просто было это, и, как это случилось со мной в прошлом, это не сработало, потому что я не обращал внимания на автозаполнение при попытке добавить метод и фактически заканчивал тем, что реализовал tableView:didDeselectRowAtIndexPath: вместо tableView:didSelectRowAtIndexPath:.


7

Убедитесь, что вы реализовали, tableView:didSelectRowAtIndexPathа неtableView:didDeSelectRowAtIndexPath

Это было получено мной не раз!


5

Я знаю, что старый, и проблема была решена, но была похожая проблема, я думал, что проблема была с моим пользовательским UITableViewCell, но решение было совершенно другим - я перезагружаю XCode :) и затем работает нормально! почти как винда :)


5

Если ваш табличный вид находится в режиме редактирования (например, [tableView setEditing:YES animated:NO];), вам необходимо установитьtableView.allowsSelectionDuringEditing = YES;


4

Еще одна ошибка, которую вы могли бы сделать (как и я): если вы установите переход на камеру, didSelectRowAtIndexPathне называется. Вместо этого вы должны установить свои сегменты на контроллере вида.


4

Ни один из этих ответов не работал для меня. Примерно через час я понял что-то очень коварное:

У меня есть вид таблицы внутри ячейки другого вида таблицы. Я решил сделать вложение, которое, помимо прочего, содержит внутреннее табличное представление. Я назвал это представление contentView и подключил его в xib.

Оказывается, что UITableViewCell уже имеет contentView и делает с ним странные вещи. Проблема разрешилась, когда я переименовал свойство в mainContentView и снова подключил представление к этому переименованному свойству.


4

В моем случае, я динамически вычислять высоту TableView«с SuperViewво время загрузки. Из-за просчета, TableViewбыл расположен за пределами SuperView. Объект TableViewбыл нарисован нормально, однако все взаимодействие было отключено (и didSelectRowAtIndexPathникогда не вызывалось) Очень трудно обнаружить, так как нет визуальной индикации того, что TableViewон «недоступен».


4

В моем случае проблема заключалась в том, что у меня был UITableViewCellподкласс, и я реализовал эти два метода: touchesBegan:withEvent:& touchesEnded:withEventдля обработки необычной анимации на ощупь. Но я забыл добавить [super touchesBegan:touches withEvent:event];метод объявления, [super touchesEnded:touches withEvent:event];чтобы сообщить родителю ячейки о касании.

Поэтому изменение кода на следующее решило мою проблему:

-(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
Могу подтвердить, что это вызвало проблему ОП для меня, в частности
Джош Вольф

4

В моем случае решение состояло в том, чтобы изменить НЕТ на ДА в приведенной ниже функции.

iOS 9+

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

Это тоже была моя проблема. У меня есть несколько реализаций tableView и я забыл разделить два tableViews в этом методе.
тестирование turing
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.