it-swarm.com.ru

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

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

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

274
Matt Pfefferle

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

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

92
Hunter

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

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

530
CGee

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

UITableView selection kind

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

472
Dennis Krut

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

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

279
bugloaf

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

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

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

149
Old McStopher

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

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

enter image description here

в коде с 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
83
Bartłomiej Semańczyk

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

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

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

63
gilm

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

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

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

44
JackPearse

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

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

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

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

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

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

27
cpt.neverm1nd

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

 enter image description here

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

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

 enter image description here

24
Mohsin Qureshi

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

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

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

19
Jeyhun Karimov

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

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

19
spiralstairs

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

18
Groot

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

11
MB_iOSDeveloper

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

[self.tableView setDelegate:self];

[self.tableView setDataSource:self];
10
Carlos

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

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

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

10
Andrew Gorcester

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

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

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

9
Steve

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

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

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

8
gmogames

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

 enter image description here

8
Naveed Ahmad

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

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

8
HotJard

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

7
user486646

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

5
Lukasz

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

5
yvetterowe

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

iOS 9+

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

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

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

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

4
xytor

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

4
GK100

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

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

4
SleepsOnNewspapers

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

4
juanignaciosl

Хорошо, обновление здесь, поскольку я только что столкнулся с этой проблемой, и моя проблема немного отличалась от найденной здесь. 

Я посмотрел в IB и увидел, что мой делегат WAS установлен, но он был неправильно установлен на VIEW вместо владельца файла (щелкните правой кнопкой мыши на табличном представлении, чтобы увидеть, куда указывает делегат).

Надеюсь, что это помогает кому-то

3
tbone

Позаботьтесь о свойствах UITableView в раскадровке, в моем случае произошло то, что у меня в раскадровке был выбран «Выбор: одиночный выбор», что не позволяет запускать метод didSelectRowAtIndexPath.

3
Diego Maye

Если у вас есть пользовательская ячейка, не забудьте установить UserInteractionEnabled в Xib (или с помощью кода) для ячейки.

2
giuseppe

В моем случае, только одна клетка имела эту проблему. Ячейка включает выход UITextView в режиме только для чтения. Хотя до касания это было только для чтения. После нажатия клавиатура поднялась. Оказалось, что все равно нужно отключить взаимодействие.

cell.content.scrollEnabled = NO;
cell.content.editable = NO;
cell.content.userInteractionEnabled = NO;
cell.content.delegate = nil;

[cell.content resignFirstResponder];

2
Imju

В этом посте есть несколько удивительных подсказок и ответов (возможно, одна из лучших дискуссий, которые я видел!). Подсказки здесь помогли мне понять, в чем заключается моя проблема, но я все еще тратил много часов, пуская слюни на клавиатуре, пытаясь обнаружить выпуск, который был похож на другие посты. Однако, как я, наконец, обнаружил, что это было немного по-другому, поэтому я хотел поделиться, если другие тоже сталкиваются с этим.

Оказывается, моя проблема заключалась в том, что в коде суперкласс добавлял полноэкранное «представление об ошибках», которое было не скрытым, а прозрачным. Тем не менее, поскольку это было поверх просмотра таблицы, а «действие пользователя» было установлено в «ДА», оно перехватывало мои прикосновения к представлению таблицы.

Я диагностировал это, используя классную кнопку «Отладка представления Xcode». Вот снимок экрана с аннотациями, которые, я надеюсь, объясняют, что я сделал и как я в конечном итоге диагностировал проблему.

В коде я просто должен был сделать:

errorMessageView.setUserInteractionEnabled = NO;
// or
errorMessageView.hidden = YES;

 Debug View Hierarchy

2
DustinB

Если ячейка, по которой вы щелкаете, подсвечивается, но функция все еще не вызывается, дважды проверьте сигнатуру вашей функции. Это должно выглядеть так:

override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath)
2
Jeb_is_a_mess

Вероятно, это было только в моем случае, но я перезагрузил некоторые файлы из резервной копии, и все не работало, в том числе это. После полной очистки (Product> Clean или Shift + Command + K) все заработало. Возможно, что-то запуталось в скомпилированном заголовке. Скорее всего, это не проблема для вас, но стоит попробовать.

2
shim

Проверьте, имеет ли ваш viewController следующий метод:

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

если вы вернете "НЕТ", didSelectRow не будет вызываться

2
Srinath Mithra

В моем случае проблема заключалась в том, что у меня был подкласс 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
}
2
alternatiph

Убедитесь, что -heightForRowAtIndexPath не возвращает 0.

2
shyamsundar1988

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

Я использую функции, представленные в ios8, называемые самоконтроля ячеек. Я наткнулся на это сообщение в блоге которое указывает, что:

Когда таблица впервые отображается, вы можете найти некоторые из ячеек не рассчитаны должным образом. Но когда вы прокручиваете табличное представление, новое ячейки отображаются с правильной высотой строки. Чтобы обойти эту проблему, Вы можете принудительно перезагрузить компьютер после появления вида:

override func viewDidAppear(animated: Bool) {
    tableView.reloadData()
}

Это исправило проблему для меня. Даже при том, что табличное представление рендерилось правильно, обработка касания (особенно hitTest из UITableView), по-видимому, была подвержена вышеупомянутой ошибке.

1
benvolioT

У меня только что была эта проблема, однако она возникла не сразу; после выбора нескольких ячеек они перестали бы вызывать didSelectItemAtIndexPath. Я понял, что проблема заключалась в том, что для представления коллекции allowsMultipleSelection установлено в значение ИСТИНА. Поскольку ячейки никогда не отменялись, это прекращало будущие вызовы от вызова didSelectItemAtIndexPath.

1
Mark Bridges

Еще одна безумная возможность: я запускал свое приложение на iPhone 5S и использовал:

- (float)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath

как я всегда делал в прошлом.

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

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath

64-битная совместимость! качает кулак

Будьте начеку, если вы начнете вырывать волосы.

1
karlbecker_com

У меня был вызов cell.userInteractionEnabled, похороненный в каком-то настроенном коде таблицы.

Глупо, но разве не большинство ошибок?

1
HalR

Я повторил все предыдущие ответы, но ни один из них не помог мне. После некоторых проб и ошибок я нашел другое решение. У меня был UIImageView, охватывающий всю ячейку (в качестве фона). По умолчанию в UIImageView отключено взаимодействие с пользователем. Включив метод делегата взаимодействия с пользователем в режиме просмотра изображений, -didSelectRowAtIndexPath: был вызван снова . Например.

cell.imgView.userInteractionEnabled = YES;
1
Yannick Winters

У меня была эта проблема сама. Я построил кости представления в IB (просто View и TableView), и делегат не был установлен. Я отправил его Владельцу Файла, и это сработало как шарм. ::спасти::

1
indigosplinter

Другая возможная причина заключается в том, что UITableView встраивается в UIScrollView. У меня была эта проблема сегодня, потому что у меня случайно было представление прокрутки вместо нормального представления в качестве корневого представления моего контроллера.

1
Taum

Я не могу комментировать, напишите здесь . В моем случае didSelectRow работал, но не didDeselectRow. Я установил delegate и dataSource для tableView, и это решило мой случай.

0
Hot'n'Young

В моем случае проблема заключалась в объявлении метода как частного.

Это не сработало:

private func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {

Это сработало:

func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
0
Prasanna Ramaswamy

Убедитесь, что вы вызываете reloadData в главном потоке. Если вы вызываете этот метод из какого-то асинхронного метода (например, из-за какого-то сетевого запроса), табличное представление может или не может правильно реагировать (в некоторых случаях приложение может даже аварийно завершить работу).

Используйте блок кода основного потока для выполнения вызова reloadData, если вызов выполняется в каком-то другом блоке метода (в котором вы не уверены):

[[NSOperationQueue mainQueue] addOperationWithBlock:^{
    [tableView reloadData];
}];
0
Supertecnoboff

Я только что нашел другой способ не вызвать ваш метод didSelect. В какой-то момент, во время некоторой ошибки в самом объявлении func, XCode предложил добавить @nonobjc к моему методу: 

@nonobjc func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {

Это продолжит компиляцию без жалоб, но вы никогда не будете вызывать действия пользовательского интерфейса.

«Это мои два цента, и я буду хотеть, чтобы мои перемены вернулись»

0
Dilapidus
  1. Добавить @interface ExampleViewController () <UITableViewDelegate, UITableViewDataSource>

  2. Сделать делегирование в раскадровке

 enter image description here

  1. Добавить код

    - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
        UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
       NSString *cellText = cell.textLabel.text;
    }
    
0
dip

Я прочитал все ответы и полностью с ними согласен. Но в моем случае это совсем другое. У меня был новый segue для моего detailViewController, связанный напрямую с моим tableCell в StoryBoard, который вызвал это. Поэтому мне пришлось удалить этот переход из моей камеры и связать его с самой UITableViewController. Теперь, написав следующий код, он работает,

override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        tableView.deselectRow(at: indexPath, animated: true)
        // Do any operation
        performSegue(withIdentifier: "DetailSegue", sender: self)
    }

Надеюсь, что это решение поможет кому-то там!

0
Sasi M

вы должны проверить, что этот выбор должен быть единичным, и редактирование не должно быть выбрано во время редактирования, и вы изменяете настройку в свойствах uttableviewcell, также вы редактируете в стиле ячейки табличного представления, должны быть пользовательскими, а идентификатор должен быть Rid, а раздел - нет.

0
ATIQ UR REHMAN

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

Начиная с Xcode 9/Swift 4 все методы Objective-C должны быть отмечены @objc. Компилятор делает разумную работу по распознаванию того, где он должен применяться, однако он не определяет наследование. Например:

class Delegate: NSObject, UITableViewDelegate {
}

class SuperDelegate: Delegate {
    override func tableView(_ tableView: UITableView, willSelectRowAt indexPath: IndexPath) -> IndexPath? { return indexPath }
}

Это не вызовет никаких предупреждений, сбоев или ошибок сборки. Однако ваша линия не будет вызываться, пока вы не добавите @objc:

@objc class SuperDelegate: Delegate {
    override func tableView(_ tableView: UITableView, willSelectRowAt indexPath: IndexPath) -> IndexPath? { return indexPath }
}
0
Departamento B

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

0
user2110847

в моем случае я сделал небольшую ошибку, я назначен:

tableView.isUserInteractionEnabled = false

так должно быть:

tableView.isUserInteractionEnabled = true
0
Vinayak Pal