在活动的UITextField外部触摸时调用函数

时间:2012-01-11 20:46:17

标签: objective-c ios focus uitextfield

当用户触摸具有键盘焦点的UITextField之外时,如何调用自定义函数?

我的目标是调用文本字段验证功能。

我试过了:

// Dismiss Keyboard

- (void)touchesEnded: (NSSet *)touches withEvent: (UIEvent *)event {
    for (UIView* view in self.view.subviews) {
        if ([view isKindOfClass:[UITextField class]]) 
        {
            [view resignFirstResponder];
            [self validationForNoOfPassengers];
        }

    }
}

validationForNoOfPassengers是我检查验证的方法。这里的问题是,当我点击其他UI控件时,它不会调用上面的方法。仅当在屏幕外部触摸时(但不在UI控件上)才调用上述方法。有什么指导吗?

4 个答案:

答案 0 :(得分:2)

将视图控制器(或其他对象)设置为文本字段的委托。在-textFieldShouldEndEditing:-textFieldDidEndEditing:进行验证。

答案 1 :(得分:2)

修改

See my answer here以获得更好的通用解决方案,您可以将其放入任何项目中。

原始答案

其他答案建议您在文本字段委托的textFieldShouldEndEditing:textFieldDidEndEditing:方法中进行验证。正如您所发现的,当您触摸控件时,您的文本字段不会将这些消息发送给其代理。

它不会发送这些消息,因为它没有结束编辑。当您触摸另一个非文本控件时,文本字段仍然是第一响应者(键盘焦点)。

我不知道您是否只有一个或两个具有验证的文本字段,或者许多具有验证的文本字段。我不知道你是否只有一个或两个非文本控件或许多非文本控件。对你来说最好的解决方案取决于你拥有的东西。

您真正想要做的是在每次新触摸时检查是否有第一响应者,如果是,则检查新触摸是否在第一响应者之外。如果是,请将resignFirstResponder发送给当前的第一响应者(这会使textFieldShouldEndEditing:发送给其代理人),并且仅在resignFirstResponder返回YES时继续。

如果您只有一个文本字段,则可以将顶级视图设为UIView的子类,并覆盖hitTest:withEvent:方法,如下所示:

MyView.h

#import <UIKit/UIKit.h>
@interface MyView : UIView
@property (weak, nonatomic) IBOutlet UITextField *textField;
@end

MyView.m

#import "MyView.h"
@implementation MyView
@synthesize textField;
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
{
    UIView *hitView = [super hitTest:point withEvent:event];
    return (hitView != self.textField
        && self.textField.isFirstResponder
        && ![self.textField resignFirstResponder])
        ? nil : hitView;
}
@end

事实证明,hitTest:withEvent:每次触摸实际上被调用了几次(我的测试中有三次)。因此,如果验证失败,您不仅希望在textFieldShouldEndEditing:中显示警报 - 您需要跟踪警报是否已在屏幕上显示。否则,您将看到警告重复弹出。

如果你有几个文本字段,上面的方法会变得很难看。你必须检查每一个,看它是否是当前的第一响应者而不是被触摸的视图。如果您可以向系统询问当前的第一响应者,那将会容易得多。

有一种方法可以返回当前的第一响应者:您可以将firstResponder发送到[[UIApplication sharedApplication] keyWindow]以获取当前的第一响应者(如果没有第一响应者,则返回null)。 很遗憾firstResponder消息是公共API。如果您使用它,可能不允许您进入App Store。

如果您决定要使用它,请输入MyView.m

MyView.m(修订版)

#import "MyView.h"

@protocol MyViewFirstResponderProtocol
// Have to declare the message so the compiler will allow it.
- (UIResponder *)firstResponder;
@end

@implementation MyView
@synthesize textField;
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
{
    NSLog(@"hitTest for event %@", event);
    UIView *hitView = [super hitTest:point withEvent:event];
    UIResponder *firstResponder = [(id)self.window firstResponder];
    return (firstResponder
        && hitView != firstResponder
        && ![firstResponder resignFirstResponder])
        ? nil : hitView;
}
@end

答案 2 :(得分:0)

将代理设置为您的文本字段并实施textFieldDidEndEditing: 方法(在符合UITextFieldDelegate protocol的类中)和调用 你的功能:

void
do_something(void)
{
    return;
}

/* ... */

- (void)textFieldDidEndEditing:(UITextField *)textField
{
    do_something();
}

答案 3 :(得分:0)

尝试覆盖resignFirstResponder并在那里执行验证。