Ошибка collectionView didSlectRow

Здравствуйте, в конкретном viewController моего проекта у меня есть UICollectionView с пользовательской ячейкой класса. Но у меня есть большая проблема с этой функцией:

    func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
        print("tapped on a cell")
    }

когда щелчок по ячейке и мгновенное освобождение (обычный щелчок) ничего не делает, просто ничего.

если я нажму и удержу около 1 секунды, не отпуская палец, он станет серым, выделенным

И если я нажимаю и удерживаю не менее 3 секунд, отпускаю палец didSelectItemAt выполняется правильно. Я попытался сделать то же самое в другом проекте, и это отлично работает, но не в этом VC, и я действительно не вижу проблемы. VC Bugged относится к классу addTest в Main.storyboard.

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

matt 27.05.2019 01:38
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
3
1
82
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Вероятно, под представлением коллекции есть UIGesture или другая интерактивная вещь. Вы должны ЗАПРЕЩАТЬ его способность cancel touches in view в конструктор интерфейсов:

Attributes inspector

или в коде:

myTapGestureRecognizer.cancelsTouchesInView = false

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

Mojtaba Hosseini 27.05.2019 02:04

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

matt 27.05.2019 02:39

Спасибо, но я думаю, что этого достаточно для тех, кто еще не очень хорошо знаком с iOS. и я думаю, что это UITapGesture только для клавиатура. (Распространенная проблема новичков.)

Mojtaba Hosseini 27.05.2019 03:03
Ответ принят как подходящий

Проницательность Моджтабы Хоссейни очень умна, но данный ответ может быть не совсем правильным.

Оказывается, на главном экране есть UITapGestureRecognizer; если он распознает до нажатия на ячейку, он предотвращает выбор ячейки. Но если вы просто установите cancelsTouchesInView на false в этом распознавателе жестов, то они будут работать в режиме обе, а это маловероятно. Мы, безусловно, хотим, чтобы касание ячейки и нет касались распознавателя жестов касания.

Таким образом, правильное решение состоит в том, чтобы дать распознавателю жестов касания делегат и реализовать gestureRecognizerShouldBegin. Здесь мы смотрим, чтобы увидеть куда кран. Если он находится в пределах ячейки, возвращаем false; иначе возвращаем true. Таким образом, мы являемся посредником между касанием ячейки и касанием распознавателя жестов.

Вот возможная реализация, продемонстрированная в очень упрощенной форме:

extension UIView {
    func isDescendant(of whattype:UIView.Type) -> Bool {
        var sup : UIView? = self.superview
        while sup != nil {
            if (whattype == type(of:sup!)) {
                return true
            }
            sup = sup!.superview
        }
        return false
    }
}

class ViewController: UIViewController, UICollectionViewDataSource, UICollectionViewDelegate, UIGestureRecognizerDelegate {

    override func viewDidLoad() {
        super.viewDidLoad()
        let t = UITapGestureRecognizer(target: self, action: #selector(tap))
        self.view.addGestureRecognizer(t)
        t.delegate = self
    }

    @objc func tap(_:UIGestureRecognizer) {
        print("tap")
    }

    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return 1
    }

    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath)
        return cell
    }

    func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
        print("select")
    }

    func gestureRecognizerShouldBegin(_ gr: UIGestureRecognizer) -> Bool {
        if let v = gr.view {
            let loc = gr.location(in: v)
            if let v2 = v.hitTest(loc, with: nil) {
                return !v2.isDescendant(of: UICollectionViewCell.self)
            }
        }
        return true
    }
}

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

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

Mojtaba Hosseini 27.05.2019 02:48

Другие вопросы по теме