Мое приложение React Native аварийно завершает работу с NSInvalidArgumentException при переходе между экранами, содержащими компоненты TextInput. Сбой происходит, в частности, при выборе текста в одном TextInput и последующем переходе на другой экран с другим TextInput.
Сведения о сбое:
- Тип исключения: NSInvalidArgumentException
- Неустрашимое исключение: Сбой происходит в -[RCTTextInputComponentView _selectionRange]
- Основная причина: NSTextContentStorage offsetFromLocation:toLocation: с недопустимыми позициями текста
- React Native Stack: RCTTextInputComponentView _selectionRange → RCTTextInputComponentView _textInputMetrics → updateLayoutMetrics:oldLayoutMetrics:
- Откройте экран с TextInput (с помощью React-native-paper TextInput)
- Выберите текст в TextInput (клавиатура открыта)
- Перейдите назад, пока клавиатура неподвижна open
- Перейти на другой экран, который также имеет TextInput
- Приложение аварийно завершает работу, когда новый TextInput пытается смонтировать
Код: Выделить всё
-[RCTTextInputComponentView _selectionRange]
Fatal Exception: NSInvalidArgumentException
0 CoreFoundation 0xc98c8 __exceptionPreprocess
1 libobjc.A.dylib 0x317c4 objc_exception_throw
2 CoreFoundation 0x1548d4 -[NSException initWithCoder:]
3 UIFoundation 0xb757c -[NSTextContentStorage offsetFromLocation:toLocation:]
4 UIKitCore 0xe55140 -[_UITextKit2LayoutController offsetFromPosition:toPosition:]
5 UIKitCore 0x1727ef8 -[UITextInputController offsetFromPosition:toPosition:]
6 UIKitCore 0x1701d18 -[UIFieldEditor offsetFromPosition:toPosition:]
7 UIKitCore 0x1714960 -[UITextField offsetFromPosition:toPosition:]
8 [AppName] 0x218c94 -[RCTTextInputComponentView _selectionRange] + 685 (RCTTextInputComponentView.mm:685)
9 [AppName] 0x218470 -[RCTTextInputComponentView _textInputMetrics] + 658 (RCTTextInputComponentView.mm:658)
10 [AppName] 0x2172d8 -[RCTTextInputComponentView updateLayoutMetrics:oldLayoutMetrics:] + 326 (RCTTextInputComponentView.mm:326)
11 [AppName] 0x1f2e70 -[RCTMountingManager performTransaction:] + 87 (RCTMountingManager.mm:87)
12 [AppName] 0x53062c facebook::react::TelemetryController::pullTransaction(...) + 40 (TelemetryController.cpp:40)
13 [AppName] 0x1f1c54 -[RCTMountingManager performTransaction:] + 403 (function.h:403)
14 [AppName] 0x1f1b54 -[RCTMountingManager initiateTransaction:] + 247 (RCTMountingManager.mm:247)
15 libdispatch.dylib 0x1adc _dispatch_call_block_and_release
16 libdispatch.dylib 0x1b7ec _dispatch_client_callout
17 libdispatch.dylib 0x38b24 _dispatch_main_queue_drain.cold.5
18 libdispatch.dylib 0x10ec8 _dispatch_main_queue_drain
19 libdispatch.dylib 0x10e04 _dispatch_main_queue_callback_4CF
20 CoreFoundation 0x6b520 __CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__
21 CoreFoundation 0x1dd14 __CFRunLoopRun
22 CoreFoundation 0x1cc44 _CFRunLoopRunSpecificWithOptions
23 GraphicsServices 0x1498 GSEventRunModal
24 UIKitCore 0xa9ddc -[UIApplication _run]
25 UIKitCore 0x4eb0c UIApplicationMain
- React Native: [ваша версия]
- react-native-keyboard-controller: 1.19.2 (проблемная версия)
- react-native-paper: [ваша версия]
- Платформа: iOS (симулятор и устройство)
Экран 1: FirstScreen.tsx
Код: Выделить всё
import React, { useState } from 'react'
import { TextInput } from 'react-native-paper'
import { KeyboardAwareScrollView } from 'react-native-keyboard-controller'
const FirstScreen = ({ navigation }) => {
const [text, setText] = useState('')
return (
)
}
Код: Выделить всё
import React, { useState } from 'react'
import { TextInput } from 'react-native-paper'
import { KeyboardAwareScrollView } from 'react-native-keyboard-controller'
const SecondScreen = ({ navigation }) => {
const [input, setInput] = useState('')
return (
)
}
- Отключение клавиатуры перед навигацией не предотвращает сбой.
- Проблема заключается во внутреннем состоянии выбора TextInput, а не в видимости клавиатуры.
- Тестирование в старой ветке без контроллера реакции-native-keyboard-controller показало, что проблема не возникла, подтверждая, что она связана с этим package
- Сбой происходит только тогда, когда текст выбран в первом TextInput (диапазон выбора должен быть активным).
Обновление response-native-keyboard-controller с версии 1.19.2 до 1.19.5 (или более поздней) устраняет этот сбой.
Проблема заключалась в ошибке в response-native-keyboard-controller версии 1.19.2, которая неправильно обрабатывала очистку состояния выбора TextInput во время переходов навигации. При навигации между экранами с компонентами TextInput, когда выделен текст, предыдущий диапазон выбора TextInput остается в памяти с недопустимыми позициями текста. Когда React Native пытается вычислить метрики макета для нового TextInput, вызывая _selectionRange, он пытается получить доступ к недопустимым позициям текста через NSTextContentStorage offsetFromLocation:toLocation:, что приводит к сбою.
Сбой происходит именно во время цикла обновления макета React Native (
Код: Выделить всё
updateLayoutMetrics:oldLayoutMetrics:Исправление:
Код: Выделить всё
yarn upgrade react-native-keyboard-controller@^1.19.5
# or
npm update react-native-keyboard-controller@^1.19.5
Дополнительный контекст
- Подтвержденная основная причина: Тестирование в старой ветке, в которой не было контроллера реакции-native-keyboard-controller, показало, что проблема не возникла, что подтверждает, что она связана с этим пакетом.
- Затронутые компоненты: Проблема затрагивает все компоненты TextInput (как TextInput React Native, так и TextInput React-native-paper) при использовании KeyboardAwareScrollView или KeyboardAvoidingView из React-native-keyboard-controller
- Местоположение сбоя: Сбой происходит в собственном коде React Native () при попытке вычислить показатели диапазона выбора во время обновления макета
Код: Выделить всё
RCTTextInputComponentView.mm:685
Подробнее здесь: https://stackoverflow.com/questions/798 ... utcomponen
Мобильная версия