textFieldShouldEndEditing 被调用多次

发布于 2024-09-06 22:02:17 字数 1570 浏览 9 评论 0原文

我正在处理一个具有多个 UITextField 对象的视图。我的视图控制器充当 UITextFieldDelegate,并且我已实现 (BOOL)textFieldShouldEndEditing:(UITextField *)textField 方法来保存和验证正在显示的记录。

如果用户在编辑项目后单击“完成”按钮并且保存/验证失败,则会显示 UIAlertView 并将用户保留在失败的 UITextField 上验证。

我的问题是这样的——当用户点击 UITextField 时,将无法保存/验证到另一个 UITextField ,然后 (BOOL)textFieldShouldEndEditing: (UITextField *)textField 方法被多次调用,UIAlertView 多次弹出。

为什么当用户单击键盘上的“完成”时 (BOOL)textFieldShouldEndEditing:(UITextField *)textField 会调用一次,而当用户单击另一个 UITextField 时会调用多次?

这是我的代码:

- (BOOL)textFieldShouldEndEditing:(UITextField *)textField {
    NSLog(@"textFieldShouldEndEditing called by textField with text=%@", textField.text);

    currentItem.nameOrNumber = nameOrNumber.text;

    // Try to save the managed object.
    NSError *error = nil;
    if (![[currentItem managedObjectContext] save:&error]) {        
        UIAlertView *errorAlert = [[UIAlertView alloc] initWithTitle:NSLocalizedString(@"Uh Oh!",@"")
                                                             message:[error localizedDescription]
                                                            delegate:self
                                                   cancelButtonTitle:NSLocalizedString(@"OK",@"")
                                                   otherButtonTitles:nil];
        [errorAlert show];
        [errorAlert release];
        shouldEnd = NO;
    }

    return shouldEnd;
}

I am working on a view that has multiple UITextField objects. My view controller serves as the UITextFieldDelegate, and I've implemented the (BOOL)textFieldShouldEndEditing:(UITextField *)textField method to save and validate the record being displayed.

If the user clicks on the "Done" button after editing an item and the save/validate fails, then a UIAlertView is displayed and the user is kept on the UITextField that fails validation.

My problem is this -- when a user clicks from the UITextField that will fail save/validation onto another of the UITextFields, then the (BOOL)textFieldShouldEndEditing:(UITextField *)textField method is called multiple times, and the UIAlertView pops up multiple times.

Why is (BOOL)textFieldShouldEndEditing:(UITextField *)textField called once when the user clicks "Done" on the keyboard, but called multiple times when the user clicks onto another UITextField?

Here is my code:

- (BOOL)textFieldShouldEndEditing:(UITextField *)textField {
    NSLog(@"textFieldShouldEndEditing called by textField with text=%@", textField.text);

    currentItem.nameOrNumber = nameOrNumber.text;

    // Try to save the managed object.
    NSError *error = nil;
    if (![[currentItem managedObjectContext] save:&error]) {        
        UIAlertView *errorAlert = [[UIAlertView alloc] initWithTitle:NSLocalizedString(@"Uh Oh!",@"")
                                                             message:[error localizedDescription]
                                                            delegate:self
                                                   cancelButtonTitle:NSLocalizedString(@"OK",@"")
                                                   otherButtonTitles:nil];
        [errorAlert show];
        [errorAlert release];
        shouldEnd = NO;
    }

    return shouldEnd;
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

仅此而已 2024-09-13 22:02:17

我认为您的问题来自于当您编辑文本字段并直接点击另一个文本字段时调用文本字段方法的顺序。

如果我没记错的话,应该是这样的(您正在 A 上编辑并点击 B)

  • textFieldShouldBeginEditing for field B
  • textFieldShouldEndEditing for field A
  • textFieldDidEndEditing< /code> 对于字段 A
  • textFieldDidBeginEditing 对于字段 B

因此,当您使用 textFieldShouldEndEditing 方法时,文本字段 B 已经成为第一响应者。因此,当您使 UIAlertView 出现时,B 会失去焦点,从而也会调用 textFieldShouldEndEditing

当我想在文本字段开始编辑时提出视图时,这对我来说也是一个问题。我找到的解决方案是创建一个布尔类变量,指示我当前是否从一个文本字段切换到另一个文本字段。
我在 textFieldShouldBeginEditing 中将其设置为 TRUE,在 textFieldDidBeginEditing 中将其设置为 FALSE。当您处于 textFieldShouldEndEditing 中时,如果将其设置为 TRUE,则意味着用户直接点击了另一个文本字段。然后你只需要找到正确的方法来只进行一次测试(也许 shouldEndEditing 应该返回 false 或其他东西)。

I think your problem comes from the order in which textField methods are called when you are editing a textField and directly tap onto another.

If I am not mistaken, it should be something like this (you are editing on A and tap on B)

  • textFieldShouldBeginEditing for field B
  • textFieldShouldEndEditing for field A
  • textFieldDidEndEditing for field A
  • textFieldDidBeginEditing for field B

So when you are in textFieldShouldEndEditing method, textfield B already has become the first responder. So when you make the UIAlertView appear, B loses focus and thus calls textFieldShouldEndEditing too!

This also has been a problem for me when I wanted to raise a view when a textField started editing. The solution I found was to create a boolean class variable indicating whether or not I am currently switching from one textField to another.
I set it to TRUE in textFieldShouldBeginEditing and to FALSE in textFieldDidBeginEditing. When you're in textFieldShouldEndEditing, if it is set to TRUE it means the user directly tapped on another textField. Then you just have to find the right way to make your tests only once (maybe shouldEndEditing should return false or something).

不爱素颜 2024-09-13 22:02:17

另一种选择是让 UIAlertView 伪造正确的验证并将更正部分推迟到稍后的时间。像这样的东西:

- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex{
    double delayInSeconds = 0.;
    self.currentTextField.text = @"Something that won't trigger validation error";
    dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, delayInSeconds * NSEC_PER_SEC);
    dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
        // do what you need here
    });
}

Another option is to let the UIAlertView fake a correct validation and defer the correcting part to a latter time. Something like this :

- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex{
    double delayInSeconds = 0.;
    self.currentTextField.text = @"Something that won't trigger validation error";
    dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, delayInSeconds * NSEC_PER_SEC);
    dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
        // do what you need here
    });
}
醉殇 2024-09-13 22:02:17

您不能在每个文本视图中添加不同的标签并检查textFieldShouldEndEditing中的标签吗?还是我错过了重点?

Couldn't you add different tags in each textview and check the tag in the textFieldShouldEndEditing? Or have I missed the point?

夜吻♂芭芘 2024-09-13 22:02:17

每个测试领域对我来说似乎被叫了 2 次。
为什么?只是想想...也传递给了我,让我头疼

你不能做这样的事情

- (BOOL)textFieldShouldEndEditing:(UITextField *)txtField{

if(i_dont_know){
    UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Title" 
                                                    message:@"Message"
                                                   delegate:self 
                                          cancelButtonTitle:@"Ok" otherButtonTitles: nil];
    [alert show];
    [alert release];
    return false;
}

return true;}

UIAlertView 显示也试图放弃文本字段的编辑
并调用这个函数“textFieldShouldEndEditing:”...

所以我解决这个问题的方法是在界面声明中添加一个名为“shouldEndEditing”的成员变量,默认为true。
在“textFieldShouldEndEditing:”之后可以是这样的。

- (BOOL)textFieldShouldEndEditing:(UITextField *)txtField{

if(shouldEndEditing == false)
{
    shouldEndEditing = true;
    return false;
}

if(i_dont_know){
    shouldEndEditing = false;
    UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Title" 
                                                    message:@"Message"
                                                   delegate:self 
                                          cancelButtonTitle:@"Ok" otherButtonTitles: nil];
    [alert show];
    [alert release];
    return false;
}

return true;}

祝你好运...

Looks right for me to be called 2 times for each test field.
Why? just think about... had passed to me also and get me headache

You can NOT do some like this

- (BOOL)textFieldShouldEndEditing:(UITextField *)txtField{

if(i_dont_know){
    UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Title" 
                                                    message:@"Message"
                                                   delegate:self 
                                          cancelButtonTitle:@"Ok" otherButtonTitles: nil];
    [alert show];
    [alert release];
    return false;
}

return true;}

Is that the UIAlertView show is also trying to resign the editing of text field
and calling this funcion "textFieldShouldEndEditing:"...

So my way to solve this was to add a member variable called "shouldEndEditing" in the interface delaration, who is true por default.
And after the "textFieldShouldEndEditing:" can be some like this.

- (BOOL)textFieldShouldEndEditing:(UITextField *)txtField{

if(shouldEndEditing == false)
{
    shouldEndEditing = true;
    return false;
}

if(i_dont_know){
    shouldEndEditing = false;
    UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Title" 
                                                    message:@"Message"
                                                   delegate:self 
                                          cancelButtonTitle:@"Ok" otherButtonTitles: nil];
    [alert show];
    [alert release];
    return false;
}

return true;}

Good luck...

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文