iOS 使用摇动撤消粘贴到 UITextView 并覆盖 shouldChangeCharactersInRange 时发生超出范围的崩溃
iOS out of range crash when using shake to undo a paste into UITextView with overwritten shouldChangeCharactersInRange
我的 iOS 应用程序崩溃了,我有崩溃报告,但我无法找出崩溃的原因。
奇怪的是,这个崩溃是在应用程序启动后发生的,并且在崩溃报告中没有显示我的代码:
Thread 0 Crashed:
0 CoreFoundation 0x00000002069d0ea4 __exceptionPreprocess + 228
1 libobjc.A.dylib 0x0000000205ba0a50 objc_exception_throw + 56
2 CoreFoundation 0x00000002068d7484 -[NSCache init] + 0
3 Foundation 0x0000000207355b94 -[NSString substringWithRange:] + 140
4 UIKitCore 0x00000002331cd8b8 -[NSTextStorage+ 12540088 (UIKitUndoExtensions) _undoRedoAttributedSubstringFromRange:] + 152
5 UIKitCore 0x00000002331ce808 -[_UITextUndoOperationTyping undoRedo] + 340
6 Foundation 0x00000002073f6734 -[_NSUndoStack popAndInvoke] + 280
7 Foundation 0x00000002073f4790 -[NSUndoManager undoNestedGroup] + 416
8 UIKitCore 0x0000000232ed1824 __58-[UIApplication _showEditAlertViewWithUndoManager:window:]_block_invoke.2529 + 32
9 UIKitCore 0x0000000232618a58 -[UIAlertController _invokeHandlersForAction:] + 108
10 UIKitCore 0x000000023261941c __103-[UIAlertController _dismissAnimated:triggeringAction:triggeredByPopoverDimmingView:dismissCompletion:]_block_invoke.477 + 28
11 UIKitCore 0x0000000232821784 -[UIPresentationController transitionDidFinish:] + 1320
12 UIKitCore 0x0000000232825794 __56-[UIPresentationController runTransitionForCurrentState]_block_invoke.440 + 188
13 UIKitCore 0x0000000232923714 -[_UIViewControllerTransitionContext completeTransition:] + 116
14 UIKitCore 0x000000023335cc4c -[UIViewAnimationBlockDelegate _didEndBlockAnimation:finished:context:] + 744
15 UIKitCore 0x00000002333328f0 -[UIViewAnimationState sendDelegateAnimationDidStop:finished:] + 312
16 UIKitCore 0x0000000233332edc -[UIViewAnimationState animationDidStop:finished:] + 296
17 UIKitCore 0x0000000233332f7c -[UIViewAnimationState animationDidStop:finished:] + 456
18 QuartzCore 0x000000020afde500 CA::Layer::run_animation_callbacks+ 1381632 (void*) + 284
19 libdispatch.dylib 0x0000000206409484 _dispatch_client_callout + 16
20 libdispatch.dylib 0x00000002063b59a4 _dispatch_main_queue_callback_4CF$VARIANT$mp + 1068
21 CoreFoundation 0x0000000206960ce4 __CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__ + 12
22 CoreFoundation 0x000000020695bbac __CFRunLoopRun + 1964
23 CoreFoundation 0x000000020695b0e0 CFRunLoopRunSpecific + 436
24 GraphicsServices 0x0000000208bd4584 GSEventRunModal + 100
25 UIKitCore 0x0000000232ec0c00 UIApplicationMain + 212
26 MyApplication 0x00000001009489fc main (main.m:17)
27 libdyld.dylib 0x0000000206419bb4 start + 4
重现步骤:
- 使用
UITextField
实施应用
- 实施
UITextFieldDelegate
协议并分配UITextField delegate
- 实施
-(BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
方法 Return 否
方法
- 运行 应用并尝试将文本粘贴到
UITextField
并观察到实际上没有粘贴任何文本
- 摇动phone触发撤消提示
- 点击提示中的撤消按钮并观察崩溃
任何帮助将不胜感激
如果 UITextView
或 UITextField
的文本在更改时以编程方式更改,撤消管理器将不会更新并将跟踪错误操作。
为避免崩溃,我们应该重置撤消管理器,使其不包含脏操作。
[textField.undoManager removeAllActions];
如果有人仍然面临此崩溃,请尝试将其设置为 textView 的自定义 class。
class MessageTextView: UITextView {
override var attributedText: NSAttributedString? {
didSet {
self.undoManager?.removeAllActions()
}
}
override var text: String? {
didSet {
self.undoManager?.removeAllActions()
}
}
}
我的 iOS 应用程序崩溃了,我有崩溃报告,但我无法找出崩溃的原因。 奇怪的是,这个崩溃是在应用程序启动后发生的,并且在崩溃报告中没有显示我的代码:
Thread 0 Crashed:
0 CoreFoundation 0x00000002069d0ea4 __exceptionPreprocess + 228
1 libobjc.A.dylib 0x0000000205ba0a50 objc_exception_throw + 56
2 CoreFoundation 0x00000002068d7484 -[NSCache init] + 0
3 Foundation 0x0000000207355b94 -[NSString substringWithRange:] + 140
4 UIKitCore 0x00000002331cd8b8 -[NSTextStorage+ 12540088 (UIKitUndoExtensions) _undoRedoAttributedSubstringFromRange:] + 152
5 UIKitCore 0x00000002331ce808 -[_UITextUndoOperationTyping undoRedo] + 340
6 Foundation 0x00000002073f6734 -[_NSUndoStack popAndInvoke] + 280
7 Foundation 0x00000002073f4790 -[NSUndoManager undoNestedGroup] + 416
8 UIKitCore 0x0000000232ed1824 __58-[UIApplication _showEditAlertViewWithUndoManager:window:]_block_invoke.2529 + 32
9 UIKitCore 0x0000000232618a58 -[UIAlertController _invokeHandlersForAction:] + 108
10 UIKitCore 0x000000023261941c __103-[UIAlertController _dismissAnimated:triggeringAction:triggeredByPopoverDimmingView:dismissCompletion:]_block_invoke.477 + 28
11 UIKitCore 0x0000000232821784 -[UIPresentationController transitionDidFinish:] + 1320
12 UIKitCore 0x0000000232825794 __56-[UIPresentationController runTransitionForCurrentState]_block_invoke.440 + 188
13 UIKitCore 0x0000000232923714 -[_UIViewControllerTransitionContext completeTransition:] + 116
14 UIKitCore 0x000000023335cc4c -[UIViewAnimationBlockDelegate _didEndBlockAnimation:finished:context:] + 744
15 UIKitCore 0x00000002333328f0 -[UIViewAnimationState sendDelegateAnimationDidStop:finished:] + 312
16 UIKitCore 0x0000000233332edc -[UIViewAnimationState animationDidStop:finished:] + 296
17 UIKitCore 0x0000000233332f7c -[UIViewAnimationState animationDidStop:finished:] + 456
18 QuartzCore 0x000000020afde500 CA::Layer::run_animation_callbacks+ 1381632 (void*) + 284
19 libdispatch.dylib 0x0000000206409484 _dispatch_client_callout + 16
20 libdispatch.dylib 0x00000002063b59a4 _dispatch_main_queue_callback_4CF$VARIANT$mp + 1068
21 CoreFoundation 0x0000000206960ce4 __CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__ + 12
22 CoreFoundation 0x000000020695bbac __CFRunLoopRun + 1964
23 CoreFoundation 0x000000020695b0e0 CFRunLoopRunSpecific + 436
24 GraphicsServices 0x0000000208bd4584 GSEventRunModal + 100
25 UIKitCore 0x0000000232ec0c00 UIApplicationMain + 212
26 MyApplication 0x00000001009489fc main (main.m:17)
27 libdyld.dylib 0x0000000206419bb4 start + 4
重现步骤:
- 使用
UITextField
实施应用
- 实施
UITextFieldDelegate
协议并分配UITextField delegate
- 实施
-(BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
方法 Return 否 方法 - 运行 应用并尝试将文本粘贴到
UITextField
并观察到实际上没有粘贴任何文本 - 摇动phone触发撤消提示
- 点击提示中的撤消按钮并观察崩溃
任何帮助将不胜感激
如果 UITextView
或 UITextField
的文本在更改时以编程方式更改,撤消管理器将不会更新并将跟踪错误操作。
为避免崩溃,我们应该重置撤消管理器,使其不包含脏操作。
[textField.undoManager removeAllActions];
如果有人仍然面临此崩溃,请尝试将其设置为 textView 的自定义 class。
class MessageTextView: UITextView {
override var attributedText: NSAttributedString? {
didSet {
self.undoManager?.removeAllActions()
}
}
override var text: String? {
didSet {
self.undoManager?.removeAllActions()
}
}
}