UITapGestureRecognizer打破了UITableView的didSelectRowAtIndexPath

我写了自己的function,当键盘出现时向上滚动文本字段。 为了通过从文本字段中消除键盘来closures键盘,我创build了一个UITapGestureRecognizer ,它可以在点击时关注文本字段上的第一个响应者。

现在,我还为文本字段创build了一个自动完成function,在文本字段下方创build一个UITableView ,并在用户input文本时用项目填充它。

但是,在自动完成表中select其中一个条目时, didSelectRowAtIndexPath不会被调用。 相反,似乎轻拍手势识别器被调用,只是辞去第一响应者。

我猜测有一些方法可以告诉水龙头手势识别器不断地将点击消息传递给UITableView ,但我无法弄清楚它是什么。 任何帮助将非常感激。

好吧,最后通过手势识别器文档search后find它。

解决scheme是实现UIGestureRecognizerDelegate并添加以下内容:

 //////////////////////////////////////////////////////////// // UIGestureRecognizerDelegate methods #pragma mark UIGestureRecognizerDelegate methods - (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch { if ([touch.view isDescendantOfView:autocompleteTableView]) { // Don't let selections of auto-complete entries fire the // gesture recognizer return NO; } return YES; } 

那照顾了它。 希望这也能帮助其他人。

解决这个问题最简单的方法是:

 UITapGestureRecognizer *tapRec = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tap:)]; [tapRec setCancelsTouchesInView:NO]; 

这可以让UIGestureRecognizer识别轻敲,并将触摸传递给下一个响应者。 这种方法的一个意想不到的结果是,如果你有一个UITableViewCell屏幕,推动另一个视图控制器。 如果用户点击该行来closures键盘,则键盘和推动都将被识别。 我怀疑这是你的意图,但是这种方法适用于很多情况。

另外,扩展Robert的答案,如果你有一个指向tableview的指针,那么你可以直接比较它的类,而不必转换成一个string,并希望苹果不改变命名:

 - (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch { if([touch.view class] == tableview.class){ return //YES/NO } return //YES/NO } 

请记住,您还必须声明UIGestureRecognizer具有包含此代码的委托。

将您的识别器的cancelsTouchesInView设置为false。 否则,它“消耗”自己的触觉,并不会传递给表视图。 这就是select事件从未发生的原因。

例如swift

 let tapOnScreen: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: "CheckTheTime") tapOnScreen.cancelsTouchesInView = false view.addGestureRecognizer(tapOnScreen) 

对于Swift(根据@Jason的回答):

 class MyAwesomeClass: UIViewController, UIGestureRecognizerDelegate private var tap: UITapGestureRecognizer! override func viewDidLoad() { super.viewDidLoad() self.tap = UITapGestureRecognizer(target: self, action: "viewTapped:") self.tap.delegate = self self.view.addGestureRecognizer(self.tap) } // UIGestureRecognizerDelegate method func gestureRecognizer(gestureRecognizer: UIGestureRecognizer, shouldReceiveTouch touch: UITouch) -> Bool { if touch.view?.isDescendantOfView(self.tableView) == true { return false } return true } 

我可能有一个更好的解决scheme,在表视图上添加轻击手势,但同时允许单元格select:

 func gestureRecognizer(gestureRecognizer: UIGestureRecognizer, shouldReceiveTouch touch: UITouch) -> Bool { if gestureRecognizer is UITapGestureRecognizer { let location = touch.locationInView(tableView) return (tableView.indexPathForRowAtPoint(location) == nil) } return true } 

我只是在用户正在点击屏幕的位置寻找一个单元格。 如果没有find索引path,那么我让手势接收触摸,否则我取消它。 对我来说,这很好。

类似的解决scheme是实现gestureRecognizer:shouldReceiveTouch:使用视图的类来确定要采取的行动。 这种方法的优点是不会屏蔽在表格周围的区域(这些区域的视图仍然从UITableView实例下降,但不代表单元格)。

这也有一个奖金,它可以在单个视图中使用多个表格(无需添加额外的代码)。

警告:有一个假设,苹果不会改变类名。

 - (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch { return ![NSStringFromClass([touch.view class]) isEqualToString:@"UITableViewCellContentView"]; } 

虽然已经很晚了,许多人发现上述build议工作得很好,但是我还是无法得到Jason或者TMilligan的方法。

我有一个静态 tableView与多个单元格包含textFields接收数字input只使用数字键盘。 这对我来说很理想:

 - (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch { if(![touch.view isKindOfClass:[UITableViewCell class]]){ [self.firstTF resignFirstResponder]; [self.secondTF resignFirstResponder]; [self.thirdTF resignFirstResponder]; [self.fourthTF resignFirstResponder]; NSLog(@"Touches Work "); return NO; } return YES; } 

确保你已经在.h文件中实现了这个<UIGestureRecognizerDelegate>

这行![touch.view isKindOfClass:[UITableViewCell class]]检查是否轻击tableViewCell并closures任何活动的键盘。

简单的解决scheme是使用UITableViewCell中的UIControl实例来获取触摸。 您可以使用userInteractionEnables == NO添加任何视图到UIControl来获取水龙头。

这是我的解决scheme,它将识别器的shouldReceiveTouch直接绑定到键盘是否显示。

在您的轻按手势识别器代表:

 #pragma mark - UIGestureRecognizerDelegate - (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch { if ([PFXKeyboardStateListener sharedInstance].visible) { return YES; } return NO; } 

PFXKeyboardStateListener.h

 @interface PFXKeyboardStateListener : NSObject { BOOL _isVisible; } + (PFXKeyboardStateListener *)sharedInstance; @property (nonatomic, readonly, getter=isVisible) BOOL visible; @end 

PFXKeyboardStateListener.m

 static PFXKeyboardStateListener *sharedInstance; @implementation PFXKeyboardStateListener + (PFXKeyboardStateListener *)sharedInstance { return sharedInstance; } + (void)load { @autoreleasepool { sharedInstance = [[self alloc] init]; } } - (void)dealloc { [[NSNotificationCenter defaultCenter] removeObserver:self]; } - (BOOL)isVisible { return _isVisible; } - (void)didShow { _isVisible = YES; } - (void)didHide { _isVisible = NO; } - (id)init { if ((self = [super init])) { NSNotificationCenter *center = [NSNotificationCenter defaultCenter]; [center addObserver:self selector:@selector(didShow) name:UIKeyboardDidShowNotification object:nil]; [center addObserver:self selector:@selector(didHide) name:UIKeyboardWillHideNotification object:nil]; } return self; } @end 

你可能想更新键盘监听器的单例模式,我还没有得到它。 希望这适用于其他人以及它为我工作。 ^^

为UIGestureRecognizer的委托实现此方法:

 - (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch { UIView *superview = touch.view; do { superview = superview.superview; if ([superview isKindOfClass:[UITableViewCell class]]) return NO; } while (superview && ![superview isKindOfClass:[UITableView class]]); return superview != nil; } 

在迅速,你可以在里面使用

 func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) { if CheckTheTime() == true { // do something }else{ } } func CheckTheTime() -> Bool{ return true } 

我的情况是不同的,包括在self.view上的uisearchbar和uitableview。 我想通过触摸视图来解开uisearchbar键盘。

 var tapGestureRecognizer:UITapGestureRecognizer? override func viewWillAppear(animated: Bool) { tapGestureRecognizer = UITapGestureRecognizer(target: self, action:Selector("handleTap:")) } 

在UISearchBar委托方法:

 func searchBarShouldBeginEditing(searchBar: UISearchBar) -> Bool { view.addGestureRecognizer(tapGestureRecognizer!) return true } func searchBarShouldEndEditing(searchBar: UISearchBar) -> Bool { view.removeGestureRecognizer(tapGestureRecognizer!) return true } 

当用户触摸self.view时:

 func handleTap(recognizer: UITapGestureRecognizer) { sampleSearchBar.endEditing(true) sampleSearchBar.resignFirstResponder() }