You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
## 📜 Description
Avoid `ensureLayout` calls.
## 💡 Motivation and Context
The issue stems from the fact that `ensureLayout` changes internal state
of the input, and when react-native changes something internally it
relies that certain state should be present, but `ensureLayout` changes
this state, so as a result it leads to crash described in
#1173
I've been thinking a lot on how to fix this issue, and the only way I
found (why exactly the issue happens) is because JS updates input of the
state:
```objc
if (_mostRecentEventCount == _state->getData().mostRecentEventCount) {
_comingFromJS = YES;
[self _setAttributedString:RCTNSAttributedStringFromAttributedStringBox(data.attributedStringBox)];
_comingFromJS = NO;
}
```
If we look further in the code we can find that this flag filters-out
undesired events:
```objc
- (void)textInputDidChange
{
if (_comingFromJS) {
return;
}
```
and
```objc
- (void)textInputDidChangeSelection
{
if (_comingFromJS) {
return;
}
```
So I decided to use the same approach and ignore events if
`_comingFromJS` is `true`. Fortunately I have an access to this through
`textInputDelegate` field (and the n I can easily get an access to
`_comingFromJS`. This field is private so I had to use `value(forKey`.
On paper architecture this field is not available (it doesn't exist) so
direct calls to `value(forKey` will lead to crash. I've tried to use the
same approach as in
#785
but `responds` in this case will return `false` and I'll never get
`_isComingFromJS`.
To overcome this problem I created small objc extensions that simply
tries to get a field and in case of exception returns `nil` (we can
catch exception in objc, but that exception is not propagated to swift
code, so in swift case the app will simply crash).
And since I created a safe version of `value(forKey` I also decided to
get rid off `responds` check in `nativeId` querying and rewrite it to
`safeValue(forKey`.
Checked that
#785
and
#1148
are not reproducible
Closes#1173#1168
## 📢 Changelog
<!-- High level overview of important changes -->
<!-- For example: fixed status bar manipulation; added new types
declarations; -->
<!-- If your changes don't affect one of platform/language below - then
remove this platform/language -->
### iOS
- don't use `ensureLayout` method;
- added `_safeValue` method in ObjC and `safeValue` extension in Swift;
- use new `safeValue` method (instead of `responds` + access);
- return `false` from `canSelectionFitIntoLayout` if `_comingFromJS` is
`true`.
## 🤔 How Has This Been Tested?
Tested on iPhone 16 Pro (iOS 26).
## 📸 Screenshots (if appropriate):
https://github.com/user-attachments/assets/2b2b42c8-cd3e-4f97-ad06-9b04f21ddca1
## 📝 Checklist
- [x] CI successfully passed
- [x] I added new mocks and corresponding unit-tests if library API was
changed
0 commit comments