【问题标题】:textFieldShouldEndEditing called multiple times多次调用 textFieldShouldEndEditing
【发布时间】:2010-06-25 21:04:46
【问题描述】:

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

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

我的问题是——当用户从 UITextField 中单击将无法保存/验证到另一个 UITextFields 时,(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;
}

【问题讨论】:

    标签: ios iphone objective-c uitextfield uitextfielddelegate


    【解决方案1】:

    我认为您的问题来自在编辑 textField 并直接点击另一个时调用 textField 方法的顺序。

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

    • textFieldShouldBeginEditing 用于字段 B
    • textFieldShouldEndEditing 用于字段 A
    • textFieldDidEndEditing 用于字段 A
    • textFieldDidBeginEditing 用于字段 B

    所以当您在textFieldShouldEndEditing 方法中时,文本字段B 已经成为第一响应者。所以当你让 UIAlertView 出现时,B 会失去焦点,因此也会调用textFieldShouldEndEditing

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

    【讨论】:

      【解决方案2】:

      另一种选择是让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
          });
      }
      

      【讨论】:

        【解决方案3】:

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

        【讨论】:

          【解决方案4】:

          对于每个测试字段,我被调用 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”的成员变量,它是真正的por default。 而后面的“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;}
          

          祝你好运……

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2018-10-19
            • 2013-03-31
            • 2019-12-16
            • 2015-01-16
            • 2017-12-17
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多