我已经编写了自己的函数,当键盘出现时滚动文本字段。为了通过点击离开文本字段来取消键盘,我创建了一个UITapGestureRecognizer,它负责在点击离开时放弃文本字段上的第一个响应器。

现在我还为文本字段创建了一个自动完成,它在文本字段的下面创建了一个UITableView,并在用户输入文本时用项目填充它。

但是,当选择自动补全表中的一个条目时,不会调用didSelectRowAtIndexPath。相反,它似乎是点击手势识别器被调用,只是辞职第一响应器。

我猜有一些方法告诉点击手势识别器继续将点击消息传递给UITableView,但我不知道它是什么。任何帮助都将不胜感激。


当前回答

我认为没有必要编写代码块,只是简单地设置 cancelsTouchesInView为false, 默认为true,你只需要设置为false。 如果你在代码中使用UITapGesture对象,同时也使用UIScrollView(tableview, collectionview),那么将此属性设置为false

let tap: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(self.dismissKeyboard))
tap.cancelsTouchesInView = false
view.addGestureRecognizer(tap)

其他回答

下面是我的解决方案,它将识别器的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

你可能想要更新键盘监听器的单例模式,我还没有得到它。希望这对每个人都有用,就像对我一样。^ ^

Swift解决方案将于2021年生效。对于这个解决方案,你不需要有对表视图的引用。

func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool {
    //return !(touch.view is UITableViewCell) <-- doesn't work, the type of the touched class is not UITableViewCell anymore
    
    var v = touch.view
    while v != nil {
        if v is UITableView { return false }
        v = v?.superview
    }
    return true
}

用法:

let gestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(YOUR_METHOD))
gestureRecognizer.delegate = self
YOUR_VIEW.addGestureRecognizer(gestureRecognizer)

虽然现在已经很晚了,很多人发现上面的建议还不错,但我无法让Jason或TMilligan的方法起作用。

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

- (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>。

这条线!view isKindOfClass:[UITableViewCell类]]检查tableViewCell是否被点击,并解散任何活动键盘。

对于Swift 5中的CollectionView:

func gestureRecognizer(gestureRecognizer: UIGestureRecognizer, shouldReceiveTouch touch: UITouch) -> Bool {
    if gestureRecognizer is UITapGestureRecognizer {
        let location = touch.location(in: mCollectionView)
        return (mCollectionView.indexPathForItem(at: location) == nil)
    }
    return true
}

我可能有一个更好的解决方案,在表格视图上添加一个点击手势,但同时允许单元格选择:

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

我只是在屏幕上用户点击的地方寻找一个单元格。如果没有找到索引路径,那么我让手势接收触摸,否则我取消它。对我来说效果很好。