-didSelectRowAtIndexPath: не викликається


295

Я пишу додаток для iOS із поданням таблиці всередині подання вкладки. В моєму UITableViewController, я реалізований -tableView:didSelectRowAtIndexPath:, але коли я вибираю рядок під час виконання, метод не викликається. Перегляд таблиці заповнюється, тому я знаю, що викликаються інші методи tableView в моєму контролері.

Хтось має ідеї, що я, можливо, накрутив, щоб це сталося?


79
також у вас може бути жест Recognizer поверх UITableView, який поглинає виділення .. (одна з можливостей)
M.Othman

Будьте уважні, якщо перегляд таблиці заповнений, це означає, що DataSource добре налаштований. Вибір є частиною методів Delegate. Тож, можливо, DataSource добре налаштований, але не Делегат!
Томас Беснехард

1
Привіт, М.Отман, ваш коментар - це саме те, що було не так з моїм власним питанням. Чи знаєте ви, як змусити gestureRecognizer працювати "з" UITableView?
yhl

15
Я помічаю, що якщо натиснути і утримувати, то в кінці кінця дзвонить -didSelectRowAtIndexPath. Я з'ясував шапку, тому що у мене є розпізнавальний жест на дотик, і цей жест повинен спочатку провалитися, перш ніж отримати дотик. Розпізнавальник жестів, хоч і дивно, на анімацію вибору таблиці не впливає.
Hlung

6
У мене була така ж проблема і у мене була щаслива можливість дізнатися, що ви не можете мати жестовий рекогнізатор поверх UITableView. Дякую М. Отман!
vnchopra

Відповіді:


97

Здається, можливо, клас не є UITableViewDelegateдля цього подання таблиці, хоча UITableViewControllerпередбачається встановити це автоматично.

Чи є шанс ви скинути делегата на якийсь інший клас?


7
Я виявив, що, хоча моїм контролером був UITableViewController, я використовував звичайний старий віджет UIViewController в UI Builder. Це не працює. Коли я видалив віджет UIViewController і скинув на його місце UITableViewController, все працювало.
Метт Пфефферле

1
Ще один прикордонний випадок для всіх - я з'єднав делегата в коді і забув, що раніше провів делегата через дошку розробки .... останній, щоб встановити його, виграє.
Олівер Данджі

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

1
myTableViewController.tableView.delegate = xxx
Мисливець

534

На всякий випадок, коли хтось зробив таку ж дурну помилку, як я:

Перевірте, чи може ім'я методу того, що ви очікуєте від того, didSelectщоб випадково потрапити didDeselectв якийсь спосіб. На це мені знадобилося близько двох годин ...


47
Тут же питання. Це тому, що XCode автоматично завершує відмінити вибір перед Select.
користувач1021430

Так само я встановив enableSelection = false, що, як видалення будь-якої виділення виділення, також запобігає натисканню комірки!
djinne95

503

Інша річ, яка може призвести до проблеми - це не вибраний вид вибору:

Вибір вибору UITableView

Має бути Single Selectionдля нормального відбору, не повинно бути No Selection.

Щоб це зробити програмно, виконайте:

tableView.allowsSelection = YES

4
Я продовжую стикатися з цим, тому що у мене є сцени, які завжди перебувають у режимі редагування, і я забуваю змінити типовий параметр "Немає вибору під час редагування".
Симетричний

3
Ви можете додати цей рядок у свій -viewDidLoad метод переглядуControlller NSParameterAssert (self.tableView.allowsSelection);
Микола Шубенков

для тих, хто спостерігав tableView.rx.itemSelected.subscribe не передзвонив, це проблема і вище виправлення працює
Dhilip

настільки корисно, коли ви переймаєте деяку кодову базу, і вона містить код за допомогою кнопок з тегами, а не didSelectRow, при цьому цей вибір вимкнено в дошці 🙄
Нітін Алабур

це таблицяПерегляд поведінки за замовчуванням?
Скорбота

296

Інша можливість полягає в тому, що UITapGestureRecognizer може їсти події, як це було тут: https://stackoverflow.com/a/9248827/214070

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


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

26
У мене була та сама проблема, що і ви @ coolcool1994 щойно реалізували [tap setCancelsTouchesInView: НЕТ]; і вирішив питання.
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 * gestureG [[gesture = [UestableGesturec [[UestableGecReggerer * [Uestable = [UestableGecReggerer] ] в цьому]; gesture.cancelsTouchesInView = НІ; [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, це виправлено.
Коф

1
@Kof прибив це. Створення UITableViewCell в конструкторі інтерфейсів Xcode 5 створює його з увімкненою взаємодією користувача = ТАК. Поганий Xcode 5!
jsd

44

У мене була така ж проблема. І це було важко знайти. Але десь у моєму коді було таке:

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

Має бути return indexPath, інакше -tableView:didSelectRowAtIndexPath:не називається.


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

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

38

Якщо ви додали gestureRecognizer поверх UITableView, виклик didSelectRowAtIndexPathне буде.

Тому вам потрібно використовувати метод делегування gestureRecognizer, щоб уникнути дотику до конкретного вигляду.

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

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

29

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

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

Він повинен повертати ДА для рядка, щоб зробити його обраним.


24

ВИ МОЖЕТЕ вибрати ці параметри

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

але якщо ви хочете, щоб UITableViewнатискання не було виділено, слід змінити UITableViewCellвластивості.

Виберіть "Ні один варіант" для вибору, як і нижче

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


20

Я поставив UITapGestureRecognizerна свій стіл подання, щоб відхилити клавіатуру, яка не дозволяла didSelectRowAtIndexPath:викликати. Сподіваюся, це комусь допоможе.


19

Якщо у вас є та сама проблема, що і у мене: Мабуть, цей метод не буде викликатися, якщо ваш tableView знаходиться в режимі редагування. Ви повинні встановити функцію enableSelectionDuringEditing на true.

Через це питання: Під час редагування `UITableView` не викликає didSelectRowAtIndexPath ??


19

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

Причиною було використання UITapGestureRecognizer. Я хотів, щоб клавіатура була відхилена, коли я натискав деінде. Я зрозумів, що це відміняє всі дії на дотик, тому didSelectRowAtIndexPathфункція не викликала.

Коли я коментую рядки, пов'язані з UITapGestureRecognizer, це працює. Крім того, ви можете перевірити функцію, UITapGestureRecognizer selectorякщо натискання є UITableViewCellчи ні.


14

У моєму випадку didSelctRowAtIndexPath не викликає, через те, що я вибрав жодне у властивості Selection tableView, встановлений на один вибір, вирішив мою проблему

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


11

Для Xcode 6.4, Swift 1.2. Вибір "тег" було змінено в ІБ. Я не знаю, як і чому. Встановивши його на "Один вибір", я знову зробив вибір ячеек подання таблиці. введіть тут опис зображення


10

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

Якщо увімкнено автоматичний підрахунок посилань (ARC), ви можете виявити, що навіть після призначення контролера делегатом представлення, повідомлення перегляду в контролер не надходять, оскільки ARC видаляє контролер. Очевидно, делегатний вказівник UITableView не вважається посиланням на ARC, тому, якщо це єдине посилання на нього, контролер буде розроблений. Ви можете перевірити, чи відбувається це чи ні, застосувавши метод контролера на контролері та встановивши там точку розриву або виклик NSLog.

Рішення полягає в тому, щоб відслідковувати контролер з чітким посиланням десь ще, поки ви не будете впевнені, що він вам більше не знадобиться.


Контролер, який збирається сміттям, поки його подання все ще відображається? Чи може це насправді статися?
Друкс

@Drux Так! Коли це трапилося зі мною, це була майже перша версія Obj-C зі збиранням сміття на iOS, і, чесно кажучи, вони не зробили великої роботи. Багато посилань були явно або неявно "слабкими", що, IMO, повинно було бути сильним. Що призвело до таких диваків, як збирання сміття об'єктів, що активно використовуються шаром відображення. Я не працював на iOS деякий час, тому я не маю уявлення, чи все-таки це відбувається в останній версії.
Ендрю Горчестер

У мого коду виникає проблема з розміром пам’яті, і я дещо виправив його і десь в коді відразу після цього didSelect не отримав виклик тільки в перший раз. Я не знаю, чи це виправдовує проблему чи ні.
Бурштин K

10

Не забудьте встановити джерело даних та делегувати метод viewDidLoad наступним чином:

[self.tableView setDelegate:self];

[self.tableView setDataSource:self];

Я дзвонив до джерела даних, але не делегував ... дякую!
Gmeister4

9

Моя проблема була нічим із зазначеного. І так кульгавий. Але я думав, що перелічу його тут, якщо він комусь допоможе.

У мене є " tableViewControllerце" мій "базовий" контролер, і тоді я створюю підкласи цього контролера. Я писав увесь свій код в tableView:didSelectRowAtIndexPathрутині в "базовому" класі. Повністю забуваючи, що за замовчуванням ця рутина також була створена (хоча і без коду, який нічого не робив) у всіх моїх підкласах. Тож коли я запустив свою програму, вона запустила версію коду підкласу, нічого не зробила, і засмутила мене. Звичайно, щойно я вилучив рутинну програму з підкласів, вона використовувала mt "базовий" клас класу і я займаюся бізнесом.

Я знаю. Не смійся. Але, можливо, це врятує когось ту годину, яку я втратив ...


8

Дав мої 2 копійки на це.

У мене був користувальницький UITableViewCell, і там була кнопка, яка охоплювала всю комірку, тож коли відбулося дотик, була обрана кнопка, а не комірка.

Або видаліть кнопку, або в моєму випадку я встановив значення "Інтерація користувача" ("Включення користувача") на кнопці помилковим, таким чином, клітина була вибраною.


8

Якщо ви читаєте це, то проблема все ще не вирішує.

У мене є власна комірка, де відключено прапорець " Взаємодія користувача ". Отже, я просто вмикаюсь. Удачі.


7

У мене це було, і як це сталося зі мною в минулому, це не спрацювало, тому що я не звертав уваги на автозаповнення при спробі додати метод, і я фактично закінчую реалізацію tableView:didDeselectRowAtIndexPath: замість tableView:didSelectRowAtIndexPath:.


7

Переконайтеся, що ви реалізували, tableView:didSelectRowAtIndexPathа ніtableView:didDeSelectRowAtIndexPath

Це отримує мене більше, ніж кілька разів !!


5

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


5

Якщо подання таблиці знаходиться в режимі редагування (напр. [tableView setEditing:YES animated:NO];), Вам потрібно встановитиtableView.allowsSelectionDuringEditing = YES;


4

Ще одна помилка, яку ви могли зробити (як я це зробив): якщо ви встановите сказ у камері, didSelectRowAtIndexPathне викликається. Натомість слід встановити свої канали на контролері перегляду.


4

Жодна з цих відповідей не працювала для мене. Приблизно через годину я зрозумів щось дуже підступне:

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

Виявляється, UITableViewCell вже має contentView і робить дивні речі з ним. Проблема вирішилася сама собою, коли я перейменував ресурс на mainContentView і повторно з'єднав перегляд із цим перейменованим ресурсом.


4

У моєму випадку я динамічно обчислюю висоту TableView's 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 і забув розділити два tableView в цьому методі.
turingtest
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.