1

我遇到了以下问题,不确定这是否是 iOS 错误,或者我误解了 UITextViewDelegate 回调。仅当我使用软件键盘(即使用鼠标单击屏幕键盘)时,我才能在我的设备(iPad Retina)和模拟器上重现此行为。

考虑以下人为设计的示例项目(2014 年 1 月 9 日更新)https ://www.dropbox.com/s/1q3vqfnsmmbhnuj/AutocorrectBug.zip

这是一个简单的 UITextView,将视图控制器设置为其委托,具有以下委托方法:

- (BOOL) textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text {

    if ([text isEqualToString:@" "]
        && range.length == 0
        && (range.location == 0
            || [[textView.text substringWithRange:NSMakeRange(range.location-1, 1)] isEqualToString:@"\n"])) {
                textView.backgroundColor = [UIColor yellowColor];
                return NO;
    }
    return YES;
}

我对这段代码的意图是,当用户键入一个空格(编辑:并且该空格是该行的第一个字符)时,该空格被忽略,而是发生了一些其他功能,在这种情况下 UITextView 变为黄色。

现在考虑以下步骤:

  1. 点击文本视图使其成为第一响应者
  2. 输入“Apple”,回车并记下定位
  3. 现在,输入一个空格(将文本视图变为黄色),再次输入“Apple”并回车。

预期:黄色背景和文字阅读:

Apple
Apple

观察到:黄色背景和文字阅读(由于自动更正):

Apple
 Apple

看来自动更正逻辑忽略了 textView:shouldChangeTextInRange:replacementText: 的结果。

  • 这是预期的行为吗?
  • 如果是这样,它可以解决吗?

编辑 1/9/14:只有一行上的第一个空格应该被忽略,进一步的空格应该正常处理(即插入到文本中),排除了蛮力的空格条。此外,我正在文本编辑器中处理一个大字符串(可能有数十万个字符)(意味着不断的用户输入),因此每次击键都分析整个字符串不会是高效的。

4

1 回答 1

1

是的,我在 iPad 7.0.3 模拟器上也看到了。

解决它的一种方法是添加此UITextViewDelegate方法:

- (void)textViewDidChange:(UITextView *)textView
{
    // eliminates spaces, including those introduced by autocorrect
    if ([textView.text rangeOfCharacterFromSet:[NSCharacterSet whitespaceCharacterSet]].location != NSNotFound) {
        textView.text = [textView.text stringByReplacingOccurrencesOfString:@" " withString:@""];
    }
}

更新

似乎这个委托方法在自动更正之后调用的,只是在你想要阻止的情况下(“Apple”变成“Apple”)替换文本是“Apple”而不是“”。因此,要修改实现以防止“\n”但允许文本中出现其他“”字符,您可以尝试将第一个字符text与“”进行比较,而不是与“”进行比较text

- (BOOL) textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text {
    
    // compare first character to 'space' character by decimal value
    if (text.length && [text characterAtIndex:0] == 32) {
        
        // check if previous character is a newline
        NSInteger locationOfPreviousCharacter = range.location - 1;
        if (locationOfPreviousCharacter < 0 || [textView.text characterAtIndex:locationOfPreviousCharacter] == 10) {
            textView.backgroundColor = [UIColor yellowColor];
            return NO;
        }
    }
    
    return YES;
}
于 2014-01-09T02:18:08.407 回答