Сбой iOS вне диапазона при использовании встряхивания для отмены вставки в UITextView с перезаписью shouldChangeCharactersInRange

#ios #crash-reports

#iOS #отчеты о сбоях

Вопрос:

Мое приложение 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 метод, возвращающий NO из этого метода
  • Запустите приложение и попытайтесь вставить текст в UITextField и обратите внимание, что текст фактически не вставлен
  • Встряхните телефон, чтобы вызвать запрос на отмену
  • Нажмите кнопку отмены в приглашении и увидите сбой

Любая помощь будет оценена

Комментарии:

1. можете ли вы опубликовать файлы AppDelegate и first controller sour?

2. К сожалению, я нет. Но я добавил шаги для воспроизведения сбоя.

Ответ №1:

Если текст для UITextView или UITextField изменен программно во время его изменения, диспетчер отмены не будет обновляться и будет отслеживать неправильные действия. Чтобы избежать сбоя, мы должны сбросить диспетчер отмены, чтобы он не содержал грязных действий.

 [textField.undoManager removeAllActions];
  

Ответ №2:

Если кто-то все еще сталкивается с этим сбоем, попробуйте установить это в качестве пользовательского класса для TextView.

 class MessageTextView: UITextView {
override var attributedText: NSAttributedString? {
    didSet {
        self.undoManager?.removeAllActions()
    }
}

override var text: String? {
    didSet {
        self.undoManager?.removeAllActions()
    }
  }
}