问题:

我的UITextField与带有发送功能的UIButton并列。当用户按下发送按钮时,我正在执行简单的操作:

- (IBAction)sendMessage: (id)sender {
   [self.chatService sendMessage: self.messageTextField.text];
   self.messageTextField.text = @""; // here I get exception
}

现在,当用户开始从键盘使用听写,然后在听写视图(键盘)上按完成,然后立即按发送按钮时,出现异常“范围或索引超出范围”。

可能的解决方案:

我注意到语音识别服务器正在处理数据时,其他应用程序会禁用此“发送”按钮。这恰好在两个事件之间:用户按下“完成”,结果显示在文本字段中。我希望以同样的方式解决它。

我在可以收到此通知的文档中找不到问题。我已经找到了UITextInput协议,但这不是我所需要的。

相似的主题:
  • Using Dictation - iOS 6 - DidStart-不可接受的解决方案(可能会被苹果拒绝)
  • Disable Dictation button on the keyboard of iPhone 4S / new iPad-与上述类似的方法

  • 我尝试了什么:
  • 只是捕获并忽略异常。崩溃没有发生,但是虚拟键盘变得完全无响应
  • [UITextInputMode currentInputMode].primaryLanguage等于@"dictation"时,禁用发送按钮。报告听写模式结束的通知UITextInputCurrentInputModeDidChangeNotification在听写服务提交新值之前到达,我仍然能够单击发送按钮以引起异常。当primaryLanguage损失@“dictation”值时,我可以添加延迟,但是我不喜欢这种方法。此所需的延迟很可能取决于语音识别服务的响应速度。
  • 我在不同事件上添加了一堆动作(此evets正在处理:UIControlEventEditingDidBeginUIControlEventEditingChangedUIControlEventEditingDidEndUIControlEventEditingDidEndOnExit)。好处是,看起来UIControlEventEditingChanged恰好在所需的时间触发:当用户在听写视图上按“完成”时,以及服务提交或结束听写时。所以这是到目前为止我最好的概念。 不好的是,是在其他情况下也会触发该事件,并且没有信息可以区分在哪种情况下触发了此控制事件,因此我不知道应该禁用还是启用该按钮或什么也不做。
  • 最佳答案

    我终于找到了最终的解决方案。

    它简单而优雅,将通过苹果审查,并且始终有效。只需对UIControlEventEditingChanged做出反应,并检测替换字符的存在,如下所示:

    -(void)viewDidLoad {
      [super viewDidLoad];
    
      [self.textField addTarget: self
                         action: @selector(eventEditingChanged:)
               forControlEvents: UIControlEventEditingChanged];
    }
    
    -(IBAction)eventEditingChanged:(UITextField *)sender {
      NSRange range = [sender.text rangeOfString: @"\uFFFC"];
      self.sendButton.enabled = range.location==NSNotFound;
    }
    

    旧方法

    Finlay我找到了一些解决方案。这是对概念nr 3的改进,其中包含了概念nr 2(基于that answer)的混合。
    -(void)viewDidLoad {
      [super viewDidLoad];
    
      [self.textField addTarget: self
                         action: @selector(eventEditingChanged:)
               forControlEvents: UIControlEventEditingChanged];
    }
    
    -(IBAction)eventEditingChanged:(UITextField *)sender {
      NSString *primaryLanguage = [UITextInputMode currentInputMode].primaryLanguage;
    
      if ([primaryLanguage isEqualToString: @"dictation"]) {
        self.sendButton.enabled = NO;
      } else {
        // restore normal text field state
        self.sendButton.enabled = self.textField.text.length>0;
      }
    }
    
    - (IBAction)sendMessage: (id)sender {
       [self.chatService sendMessage: self.messageTextField.text];
       self.messageTextField.text = @"";
    }
    
    - (BOOL)textFieldShouldReturn:(UITextField *)textField {
      if (self.textField.text.length==0 || !self.sendButton.enabled) {
         return NO;
       }
       [self sendMessage: textField];
       return YES;
    }
    
    // other UITextFieldDelegate methods ...
    

    现在不会出现问题,因为用户有可能在可能发生时被阻止(恰好在用户按下听写视图上的“完成”按钮以及语音识别服务产生结果时)。
    好消息是使用了公共API(只有@“dictation”可能是个问题,但我认为Apple应该接受)。

    09-13 01:39