我们知道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";
}
}
任何帮助将不胜感激!
答案 0 :(得分:15)
正在发生的是您正在键入所谓的多级文本输入,即必须在用户实际提交到基础文本之前确认输入。你得到了崩溃,因为文本只是输入的类型,并且在文本提交之前,它很容易变成其他东西。
要检测这种情况,您需要查找UITextView的markedTextRange
属性,该属性指示您是否处于此复杂输入模式。
如果属性是非零的,那么你处于这种特殊的输入模式,所以你应该使用类似的东西保护你的修改代码:
if (self.tv.markedTextRange == nil && self.tv.text.length > maxLength) {
// Perform change
}
我可以告诉崩溃是由特殊的多级文本输入模式触发的,因此在此模式激活时应避免更改文本。