textView:shouldChangeTextInRange:replacementText:返回NO,但自动更正忽略?

时间:2014-01-08 21:41:08

标签: ios objective-c uitextview uitextviewdelegate

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

考虑以下设计的示例项目(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”并按回车。
  4. 预期:黄色背景和文字阅读:

    Apple
    Apple
    

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

    Apple
     Apple
    

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

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

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

1 个答案:

答案 0 :(得分: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:@""];
    }
}

更新

似乎在autocorrection之后调用了这个委托方法 ,只是在你要防止的情况下(“Apple”变成“Apple”)替换文本是“Apple”而不是“”。因此,要修改实施以防止“\ n”但允许文本中包含其他“”字符,您可以尝试将text的第一个字符与“”进行比较,而不是将text与“”进行比较。< / p>

- (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;
}