Здравствуйте, в конкретном viewController моего проекта у меня есть UICollectionView с пользовательской ячейкой класса. Но у меня есть большая проблема с этой функцией:
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
print("tapped on a cell")
}
когда щелчок по ячейке и мгновенное освобождение (обычный щелчок) ничего не делает, просто ничего.
если я нажму и удержу около 1 секунды, не отпуская палец, он станет серым, выделенным
И если я нажимаю и удерживаю не менее 3 секунд, отпускаю палец didSelectItemAt выполняется правильно. Я попытался сделать то же самое в другом проекте, и это отлично работает, но не в этом VC, и я действительно не вижу проблемы. VC Bugged относится к классу addTest в Main.storyboard.
Вероятно, под представлением коллекции есть UIGesture
или другая интерактивная вещь. Вы должны ЗАПРЕЩАТЬ его способность cancel touches in view
в конструктор интерфейсов:
или в коде:
myTapGestureRecognizer.cancelsTouchesInView = false
Пожалуйста. Я знал, в чем проблема, без необходимости видеть ваш проект, но @matt прав! вы должны предоставить минимальный полный проверяемый пример не весь проект. Для этого случая будет достаточно некоторой информации о слоях текущего контроллера представления и кода класса.
Очень проницательно и умно! Однако теперь, когда вы так блестяще определили источник проблемы, я не думаю, что это вполне правильное решение. Я думаю, что нам нужен делегат на распознаватель жестов, чтобы предотвратить его распознавание только в том случае, когда касание находится в ячейке.
Спасибо, но я думаю, что этого достаточно для тех, кто еще не очень хорошо знаком с iOS. и я думаю, что это UITapGesture
только для клавиатура. (Распространенная проблема новичков.)
Проницательность Моджтабы Хоссейни очень умна, но данный ответ может быть не совсем правильным.
Оказывается, на главном экране есть 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
, вероятно, обрабатывает только увольнение клавиатуры, возможно, это не обязательно и это намного сложнее.
Пожалуйста, не ссылайтесь на весь код. Вместо этого выясните, как воспроизвести проблему на минимальном полном проверяемом примере.