7

正如我们所知,UITextView在 iOS 7 中它更强大,但在这里它表现得更脆弱。以下代码在 iOS 6 中使用中文输入键盘输入“rr”时工作正常,但在 iOS 7 中崩溃。

- (void)viewDidLoad
{
    [super viewDidLoad];
    self.tv = [[UITextView alloc] initWithFrame:CGRectMake(0, 100, 320, 100)];
    self.tv.backgroundColor = [UIColor yellowColor];
    self.tv.textColor = [UIColor blackColor];
    self.tv.editable = YES;
    self.tv.delegate = self;

    [self.view addSubview:self.tv];
}

-(void)textViewDidChange:(UITextView *)textView{

    int maxLength = 2;
    if (self.tv.text.length > maxLength) {
        NSLog(@"self.tv.text :%@",self.tv.text);
        NSLog(@"self.tv.text.length :%d",self.tv.text.length);
        NSLog(@"maxLength :%d",maxLength);
        self.tv.text = [self.tv.text substringToIndex:maxLength];
    }
}

日志如下:

2013-11-13 15:48:16.003 Test2[1388:70b] self.tv.text :r r
2013-11-13 15:48:16.004 Test2[1388:70b] self.tv.text.length :3
2013-11-13 15:48:16.005 Test2[1388:70b] maxLength :2
2013-11-13 15:48:16.032 Test2[1388:70b] *** Terminating app due to uncaught exception 'NSRangeException', reason: 'NSMutableRLEArray replaceObjectsInRange:withObject:length:: Out of bounds'
*** First throw call stack:
(
    0   CoreFoundation                      0x017355e4 __exceptionPreprocess + 180
    1   libobjc.A.dylib                     0x014b88b6 objc_exception_throw + 44
    2   CoreFoundation                      0x017353bb +[NSException raise:format:] + 139
    3   Foundation                          0x010ebba1 -[NSMutableRLEArray replaceObjectsInRange:withObject:length:] + 136
    4   Foundation                          0x010ebb14 -[NSMutableRLEArray deleteObjectsInRange:] + 63
    5   Foundation                          0x010ea559 -[NSConcreteMutableAttributedString replaceCharactersInRange:withAttributedString:] + 324
    6   UIFoundation                        0x02d9d9f4 __71-[NSConcreteTextStorage replaceCharactersInRange:withAttributedString:]_block_invoke + 68
    7   UIFoundation                        0x02d9d92f -[NSConcreteTextStorage replaceCharactersInRange:withAttributedString:] + 121
    8   UIKit                               0x00924d22 __53-[UITextInputController setMarkedText:selectedRange:]_block_invoke + 352
    9   UIFoundation                        0x02d9b491 -[NSTextStorage coordinateEditing:] + 48
    10  UIKit                               0x00924a38 -[UITextInputController setMarkedText:selectedRange:] + 249
    11  UIKit                               0x008fb3b1 -[UITextView setMarkedText:selectedRange:] + 63
    12  UIKit                               0x00644aa5 -[UIResponder(UITextInput_Internal) _setMarkedText:selectedRange:] + 101
    13  UIKit                               0x004031aa -[UIKeyboardImpl setMarkedText:selectedRange:inputString:searchString:] + 365
    14  UIKit                               0x00419737 -[TIKeyboardOperationSetMarkedText(UIKeyboardImpl) main] + 178
    15  Foundation                          0x0118da69 -[__NSOperationInternal _start:] + 671
    16  Foundation                          0x0110a798 -[NSOperation start] + 83
    17  UIKit                               0x0040e08a -[UIKeyboardImpl updateCandidateDisplayAsyncWithCandidateSet:documentOperation:] + 188
    18  UIKit                               0x00419041 -[TIKeyboardOperationSetCandidates(UIKeyboardImpl) main] + 112
    19  Foundation                          0x0118da69 -[__NSOperationInternal _start:] + 671
    20  Foundation                          0x0110a798 -[NSOperation start] + 83
    21  UIKit                               0x0040671d -[UIKeyboardImpl performOperations:] + 153
    22  UIKit                               0x00404f4e -[UIKeyboardImpl continueGenerateCandidatesAsynchronouslyWithOperations:] + 40
    23  UIKit                               0x00404c51 __87-[UIKeyboardImpl replyHandlerForGenerateCandidatesAsynchronouslyWithSelectedCandidate:]_block_invoke_2 + 46
    24  UIKit                               0x009381b8 -[UIKeyboardTaskQueue continueExecutionOnMainThread] + 402
    25  UIKit                               0x0093885f -[UIKeyboardTaskQueue addTask:] + 144
    26  CoreFoundation                      0x01729d1d __invoking___ + 29
    27  CoreFoundation                      0x01729c2a -[NSInvocation invoke] + 362
    28  UIKit                               0x008e63d2 -[_UIActionWhenIdle invoke] + 100
    29  UIKit                               0x008e64a6 __41-[_UIActionWhenIdle addObserverToRunLoop]_block_invoke + 36
    30  CoreFoundation                      0x0172924d _runLoopObserverWithBlockContext + 29
    31  CoreFoundation                      0x016fd53e __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__ + 30
    32  CoreFoundation                      0x016fd48f __CFRunLoopDoObservers + 399
    33  CoreFoundation                      0x016db3b4 __CFRunLoopRun + 1076
    34  CoreFoundation                      0x016dab33 CFRunLoopRunSpecific + 467
    35  CoreFoundation                      0x016da94b CFRunLoopRunInMode + 123
    36  GraphicsServices                    0x036d69d7 GSEventRunModal + 192
    37  GraphicsServices                    0x036d67fe GSEventRun + 104
    38  UIKit                               0x0022b94b UIApplicationMain + 1225
    39  Test2                               0x0000388d main + 141
    40  libdyld.dylib                       0x01d7370d start + 1
    41  ???                                 0x00000001 0x0 + 1
)
libc++abi.dylib: terminating with uncaught exception of type NSException

另外,我测试了下面的代码,用中文输入键盘输入“rr”后也崩溃了。

-(void)textViewDidChange:(UITextView *)textView{

    int maxLength = 2;
    if (self.tv.text.length > maxLength) {
        self.tv.text = @"c";
    }
}

任何帮助将不胜感激!

4

1 回答 1

17

发生的事情是您正在输入所谓的多阶段文本输入,即输入必须在实际提交到基础文本之前得到用户的确认。您会遇到崩溃,因为文本只是一种输入,并且在提交文本之前,它可以很容易地更改为其他内容。

为了检测这种情况,您正在寻找markedTextRangeUITextView 的属性,该属性指示您是否处于这种复杂的输入模式。

如果该属性不是 nil,那么您处于这种特殊的输入模式,因此您应该使用以下内容保护您的修改代码:

if (self.tv.markedTextRange == nil && self.tv.text.length > maxLength) {
    // Perform change
}

据我所知,崩溃是由特殊的多级文本输入模式触发的,因此您应该避免在此模式处于活动状态时更改文本。

于 2013-11-13T17:31:37.217 回答