设置UITextView的文本会导致崩溃

时间:2014-05-15 13:53:07

标签: ios objective-c unicode uitextview

我正在尝试设置UITextView的文本,其中包含一些非法字符,例如" Unicode字符'对象替换字符' (U + FFFC)&#34 ;.
基本上,我有一个UITextView。现在用户点击它并且键盘出现。现在我使用语音从键盘发送文本(也称为听写)。当听写处理时(那时UITextView具有与默认占位符动画对应的特殊字符),我尝试使用以下方式设置文本视图的值:

textView.text = @""

这会造成以下崩溃:

 *** Terminating app due to uncaught exception 'NSRangeException', reason: '-[__NSCFString replaceCharactersInRange:withString:]: Range or index out of bounds'

我从崩解剂中获得的堆栈跟踪:

0    CoreFoundation     __exceptionPreprocess + 130
2    CoreFoundation     -[NSException initWithCoder:]
3    CoreFoundation     mutateError + 222
4    Foundation     -[NSString stringByReplacingCharactersInRange:withString:] + 134
5    UIKit      __37-[UITextInputController textInRange:]_block_invoke + 310
6    UIFoundation       -[NSTextStorage coordinateReading:] + 36
7    UIKit      -[UITextInputController textInRange:] + 232
8    UIKit      -[TIDocumentState(UITextInputAdditions) _contextAfterPosition:inDocument:] + 190
9    UIKit      -[TIDocumentState(UITextInputAdditions) initWithDocument:] + 150
10    UIKit     +[TIDocumentState(UITextInputAdditions) documentStateOfDocument:] + 52
11    UIKit     -[UIKeyboardImpl updateForChangedSelectionWithExecutionContext:] + 288
12    UIKit     -[UIKeyboardTaskQueue continueExecutionOnMainThread] + 352
13    UIKit     -[UIKeyboardTaskQueue performTask:] + 248
14    UIKit     -[UIKeyboardImpl updateForChangedSelection] + 96
15    UIKit     -[UIKeyboardImpl selectionDidChange:] + 102
16    UIFoundation      -[NSTextStorage coordinateReading:] + 36
17    UIKit     -[UITextInputController _coordinateSelectionChange:] + 100
18    UIKit     -[UITextInputController _setSelectedTextRange:] + 604
19    UIKit     -[UITextView setAttributedText:] + 392
20    UIKit     -[UITextView setText:] + 134

我还创建了一个演示此问题的示例项目。您可以从https://dl.dropboxusercontent.com/u/80141854/TextViewDictationCheck.zip

获取此项目

可以通过以下步骤复制例外:

  1. 列表项
  2. 在xcode中运行项目。
  3. 点击文字视图。键盘出现了。
  4. 按键盘上的空格旁边的麦克风按钮。
  5. 过了一段时间(4-5秒),按完了。
  6. 现在您将看到一个在textview中移动的微调器。当微调器在textview中移动时按send。
  7. 你会得到例外。
  8. 我找到了一种避免此崩溃的方法: 在设置UITextView的文本时,我们可以使用以下代码:
    我还发现了一个在UITextView上重置文本时可以使用的解决方法:

    [self.textView setSelectedRange:NSMakeRange(0, [[self.textView textStorage] length])];
    [self.textView insertText:@""];
    [self.textView setText:@""];
    

    但是,如果我们只使用setText:来设置文本,我仍然没有理解这种崩溃的原因。

1 个答案:

答案 0 :(得分:3)

异常发生在Foundation代码中,而不是代码中。如果在处理听写时更改了字符串,则存在导致此崩溃的竞争条件。当您触摸麦克风按钮时,它会将占位符放入字符串中,然后在完成处理时将其替换为文本。如果更改字符串并删除占位符,则会导致崩溃。

修复方法是确保在处理听写时不要更改字符串。您可以通过检查当前输入模式主要语言来完成此操作。在听写正在进行时,它被设置为dictation

- (IBAction)sendPressed:(id)sender
{
    NSString *primaryLanguage = [self.textView textInputMode].primaryLanguage;
    if(![primaryLanguage isEqualToString:@"dictation"])
    {

        // Your original method body:
        NSString *textViewText = self.textView.text;
        textViewText = @"";
        self.textView.text = nil;
        self.textView.text = @"";

    }

}

如果正在进行听写,则会跳过代码以清空textview。