Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[iOS][TextInput] Avoid using -[UITextView setAttributedString:] while user is typing #19809

Conversation

mandrigin
Copy link

@mandrigin mandrigin commented Jun 19, 2018

Motivation

iOS-specific.
For languages with complex input (such as Japanese or Chinese), a user has to type multiple characters that are then merged into a single one.
If -[UITextView setAttributedString:] is used while the user is still typing, it resets the input and characters are not being treated as typed together.

This PR avoids calling this method if possible, replacing it by just copying the attributes if the string has not been changed. That preserves the state and user can continue to type Korean or Chinese characters.

Fixes #19339

Test Plan

Essentially, the steps to reproduce are described in the issue:

  1. Type some Korean characters in TextInput, such as "하늘" (buttons ,,,,).
  2. Then move the cursor to the beginning of the text, type "파란" (buttons ,,,,) this time.

Behaviour before this fix (broken)
Actual text: ㅍㅏㄹㅏㄴ하늘.
Expected text: 파란하늘.
Characters aren't combined properly.

ezgif com-resize

Behaviour after this fix (correct)
Actual text: 파란하늘.
Expected text: 파란하늘.
Characters are combined, the same behaviour is in vanilla iOS UITextView.

input-with-fix

Related PRs

Release Notes

[IOS] [BUGFIX] [TextView] - Fix Korean/Chinese/Japanese input for multiline TextView on iOS.

@react-native-bot react-native-bot added ✅Test Plan Platform: iOS iOS applications. Component: TextInput Related to the TextInput component. labels Jun 19, 2018
@facebook-github-bot
Copy link
Contributor

Thank you for your pull request and welcome to our community. We require contributors to sign our Contributor License Agreement, and we don't seem to have you on file. In order for us to review and merge your code, please sign up at https://code.facebook.com/cla. If you are contributing on behalf of someone else (eg your employer), the individual CLA may not be sufficient and your employer may need the corporate CLA signed.

If you have received this in error or have any questions, please contact us at cla@fb.com. Thanks!

@facebook-github-bot facebook-github-bot added the CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. label Jun 19, 2018
@facebook-github-bot
Copy link
Contributor

Thank you for signing our Contributor License Agreement. We can now accept your code for this (and any) Facebook open source project. Thanks!

mandrigin added a commit to status-im/status-mobile that referenced this pull request Jun 20, 2018
The fix is described here: facebook/react-native#19809

The patch:
1. A copy of patched RCTUITextView.m file
2. A pre-action in the "Build" scheme to patch the RN file. See more on
   pre-actions here: https://burcugeneci.wordpress.com/2016/05/25/scripts-we-love-xcode-builds-life-savers/
3. A build step to fail the build if the file wasn't patched.

Signed-off-by: Igor Mandrigin <i@mandrigin.ru>
@RebelBIrd
Copy link

When the TextInput has props "multiline={true}", this PR is effective.Because UITextView has that Method -[UITextView setAttributedString:].
multiline={false}.still has the problem!!

rasom added a commit to status-im/react-native that referenced this pull request Jul 5, 2018
@mandrigin
Copy link
Author

@RebelBIrd yeah, this only fixes multi-line text views... I'll try to take a look at the UITextView as well to see if that is possible to fix that there...

@facebook-github-bot
Copy link
Contributor

@mandrigin I tried to find reviewers for this pull request and wanted to ping them to take another look. However, based on the blame information for the files in this pull request I couldn't find any reviewers. This sometimes happens when the files in the pull request are new or don't exist on master anymore. Is this pull request still relevant? If yes could you please rebase? In case you know who has context on this code feel free to mention them in a comment (one person is fine). Thanks for reading and hope you will continue contributing to the project.

… text.

For languages with complex input (such as Japanese or Chinese),
where user presses multiple buttons to input one symbol,
it breaks selection and input, so it is impossible to enter characters.
@mandrigin mandrigin force-pushed the bugfix/korean-chinese-japanese-input branch from 2a08ae3 to 81960c6 Compare July 25, 2018 07:08
@mandrigin
Copy link
Author

@RebelBIrd can you check if this commit: 892212b fixes your issues? If so, I can probably just close my PR.

yenda pushed a commit to yenda/react-native that referenced this pull request Aug 13, 2018
@facebook-github-bot
Copy link
Contributor

@mandrigin I tried to find reviewers for this pull request and wanted to ping them to take another look. However, based on the blame information for the files in this pull request I couldn't find any reviewers. This sometimes happens when the files in the pull request are new or don't exist on master anymore. Is this pull request still relevant? If yes could you please rebase? In case you know who has context on this code feel free to mention them in a comment (one person is fine). Thanks for reading and hope you will continue contributing to the project.

@shergin
Copy link
Contributor

shergin commented Dec 4, 2018

@rigdern Adam, what do you think?

@shergin
Copy link
Contributor

shergin commented Dec 4, 2018

For context, here is the story behind this if statement:

IIRC, originally, this if compared strings as pure strings (as it is before the change), but later we discovered that when only attributes change on JS side, the text doesn't get updated. And we changed that to comparing them as attributed string (text + attributes).

Then we discovered that sometimes/often UITextField's version of an attributed string has additional sets of attributes which made the compare operation to fail. And we changed this back.

My idea was that we have to introduce a special custom comparing function that ignores some attributes, but eventually I haven't found time for this.

This approach is very similar to what I planned to implement, but... simpler!

@mandrigin Thank you for fixing this! Спасибо!

@facebook-github-bot facebook-github-bot added the Import Started This pull request has been imported. This does not imply the PR has been approved. label Dec 4, 2018
Copy link
Contributor

@facebook-github-bot facebook-github-bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@shergin is landing this pull request. If you are a Facebook employee, you can view this diff on Phabricator.

@mandrigin
Copy link
Author

mandrigin commented Dec 4, 2018

@shergin Спасибо! Thanks for your explanation! Yeah, text input is very hard... I see that you are trying to avoid re-implementing all the locale support that is implemented in mobile OS-es. That is a very pragmatic and wise solution.

Simplicity was my goal, because I'm just beginning my journey into React Native world, so I don't know the internals so much. Hence, I tried to be as concise and have as small of the affected code area as possible.

My fix has one gotcha. It only fixes multiline text fields, because on iOS I see that single-line text fields are UITextFields, and not UITextViews.
I can try to investigate and make a follow-up PR to fix single line text fields. We don't have this issue ourselves, mostly because we use multi-line text fields everywhere, but I think for the completeness sake I want to fix it.

@react-native-bot
Copy link
Collaborator

Igor Mandrigin merged commit f77aa4e into facebook:master.

@facebook facebook locked as resolved and limited conversation to collaborators Dec 4, 2018
@react-native-bot react-native-bot added the Merged This PR has been merged. label Dec 4, 2018
@shergin
Copy link
Contributor

shergin commented Dec 5, 2018

kelset pushed a commit that referenced this pull request Dec 12, 2018
…#19809)

Summary:
iOS-specific.
For languages with complex input (such as Japanese or Chinese), a user has to type multiple characters that are then merged into a single one.
If `-[UITextView setAttributedString:]` is used while the user is still typing, it resets the input and characters are not being treated as typed together.

This PR avoids calling this method if possible, replacing it by just copying the attributes if the string has not been changed. That preserves the state and user can continue to type Korean or Chinese characters.

Fixes #19339

<!--
  Required: Write your motivation here.
  If this PR fixes an issue, type "Fixes #issueNumber" to automatically close the issue when the PR is merged.
-->

<!--
  Required: Write your test plan here. If you changed any code, please provide us with
  clear instructions on how you verified your changes work. Bonus points for screenshots and videos!
-->

Essentially, the steps to reproduce are described in [the issue](#19339):

1. Type some Korean characters in TextInput, such as "하늘" (buttons `ㅎ`,`ㅏ`,`ㄴ`,`ㅡ`,`ㄹ`).
2. Then move the cursor to the beginning of the text, type "파란" (buttons `ㅍ`,`ㅏ`,`ㄹ`,`ㅏ`,`ㄴ`) this time.

**Behaviour before this fix (broken)**
Actual text: `ㅍㅏㄹㅏㄴ하늘`.
Expected text: `파란하늘`.
Characters aren't combined properly.

![ezgif com-resize](https://user-images.githubusercontent.com/466427/41613572-4256dda8-73f6-11e8-99a9-0ab833202b95.gif)

**Behaviour after this fix (correct)**
Actual text: `파란하늘`.
Expected text: `파란하늘`.
Characters are combined, the same behaviour is in vanilla iOS `UITextView`.

![input-with-fix](https://user-images.githubusercontent.com/466427/41613526-1aae2284-73f6-11e8-87f2-c1cef51cd83a.gif)

<!--
  Does this PR require a documentation change?
  Create a PR at https://github.com/facebook/react-native-website and add a link to it here.
-->

<!--
  Required.
  Help reviewers and the release process by writing your own release notes. See below for an example.
-->

[IOS] [BUGFIX] [TextView] - Fix Korean/Chinese/Japanese input for multiline TextView on iOS.

<!--
  **INTERNAL and MINOR tagged notes will not be included in the next version's final release notes.**

    CATEGORY
  [----------]      TYPE
  [ CLI      ] [-------------]    LOCATION
  [ DOCS     ] [ BREAKING    ] [-------------]
  [ GENERAL  ] [ BUGFIX      ] [ {Component} ]
  [ INTERNAL ] [ ENHANCEMENT ] [ {Filename}  ]
  [ IOS      ] [ FEATURE     ] [ {Directory} ]   |-----------|
  [ ANDROID  ] [ MINOR       ] [ {Framework} ] - | {Message} |
  [----------] [-------------] [-------------]   |-----------|

 EXAMPLES:

 [IOS] [BREAKING] [FlatList] - Change a thing that breaks other things
 [ANDROID] [BUGFIX] [TextInput] - Did a thing to TextInput
 [CLI] [FEATURE] [local-cli/info/info.js] - CLI easier to do things with
 [DOCS] [BUGFIX] [GettingStarted.md] - Accidentally a thing/word
 [GENERAL] [ENHANCEMENT] [Yoga] - Added new yoga thing/position
 [INTERNAL] [FEATURE] [./scripts] - Added thing to script that nobody will see
-->
Pull Request resolved: #19809

Differential Revision: D13326614

Pulled By: shergin

fbshipit-source-id: 6a5cab3f7290f0f623a6f4c29353a573eb321b0b
grabbou pushed a commit that referenced this pull request Dec 17, 2018
…#19809)

Summary:
iOS-specific.
For languages with complex input (such as Japanese or Chinese), a user has to type multiple characters that are then merged into a single one.
If `-[UITextView setAttributedString:]` is used while the user is still typing, it resets the input and characters are not being treated as typed together.

This PR avoids calling this method if possible, replacing it by just copying the attributes if the string has not been changed. That preserves the state and user can continue to type Korean or Chinese characters.

Fixes #19339

<!--
  Required: Write your motivation here.
  If this PR fixes an issue, type "Fixes #issueNumber" to automatically close the issue when the PR is merged.
-->

<!--
  Required: Write your test plan here. If you changed any code, please provide us with
  clear instructions on how you verified your changes work. Bonus points for screenshots and videos!
-->

Essentially, the steps to reproduce are described in [the issue](#19339):

1. Type some Korean characters in TextInput, such as "하늘" (buttons `ㅎ`,`ㅏ`,`ㄴ`,`ㅡ`,`ㄹ`).
2. Then move the cursor to the beginning of the text, type "파란" (buttons `ㅍ`,`ㅏ`,`ㄹ`,`ㅏ`,`ㄴ`) this time.

**Behaviour before this fix (broken)**
Actual text: `ㅍㅏㄹㅏㄴ하늘`.
Expected text: `파란하늘`.
Characters aren't combined properly.

![ezgif com-resize](https://user-images.githubusercontent.com/466427/41613572-4256dda8-73f6-11e8-99a9-0ab833202b95.gif)

**Behaviour after this fix (correct)**
Actual text: `파란하늘`.
Expected text: `파란하늘`.
Characters are combined, the same behaviour is in vanilla iOS `UITextView`.

![input-with-fix](https://user-images.githubusercontent.com/466427/41613526-1aae2284-73f6-11e8-87f2-c1cef51cd83a.gif)

<!--
  Does this PR require a documentation change?
  Create a PR at https://github.com/facebook/react-native-website and add a link to it here.
-->

<!--
  Required.
  Help reviewers and the release process by writing your own release notes. See below for an example.
-->

[IOS] [BUGFIX] [TextView] - Fix Korean/Chinese/Japanese input for multiline TextView on iOS.

<!--
  **INTERNAL and MINOR tagged notes will not be included in the next version's final release notes.**

    CATEGORY
  [----------]      TYPE
  [ CLI      ] [-------------]    LOCATION
  [ DOCS     ] [ BREAKING    ] [-------------]
  [ GENERAL  ] [ BUGFIX      ] [ {Component} ]
  [ INTERNAL ] [ ENHANCEMENT ] [ {Filename}  ]
  [ IOS      ] [ FEATURE     ] [ {Directory} ]   |-----------|
  [ ANDROID  ] [ MINOR       ] [ {Framework} ] - | {Message} |
  [----------] [-------------] [-------------]   |-----------|

 EXAMPLES:

 [IOS] [BREAKING] [FlatList] - Change a thing that breaks other things
 [ANDROID] [BUGFIX] [TextInput] - Did a thing to TextInput
 [CLI] [FEATURE] [local-cli/info/info.js] - CLI easier to do things with
 [DOCS] [BUGFIX] [GettingStarted.md] - Accidentally a thing/word
 [GENERAL] [ENHANCEMENT] [Yoga] - Added new yoga thing/position
 [INTERNAL] [FEATURE] [./scripts] - Added thing to script that nobody will see
-->
Pull Request resolved: #19809

Differential Revision: D13326614

Pulled By: shergin

fbshipit-source-id: 6a5cab3f7290f0f623a6f4c29353a573eb321b0b
@hramos hramos removed Import Started This pull request has been imported. This does not imply the PR has been approved. labels Feb 6, 2019
t-nanava pushed a commit to microsoft/react-native-macos that referenced this pull request Jun 17, 2019
…facebook#19809)

Summary:
iOS-specific.
For languages with complex input (such as Japanese or Chinese), a user has to type multiple characters that are then merged into a single one.
If `-[UITextView setAttributedString:]` is used while the user is still typing, it resets the input and characters are not being treated as typed together.

This PR avoids calling this method if possible, replacing it by just copying the attributes if the string has not been changed. That preserves the state and user can continue to type Korean or Chinese characters.

Fixes facebook#19339

<!--
  Required: Write your motivation here.
  If this PR fixes an issue, type "Fixes #issueNumber" to automatically close the issue when the PR is merged.
-->

<!--
  Required: Write your test plan here. If you changed any code, please provide us with
  clear instructions on how you verified your changes work. Bonus points for screenshots and videos!
-->

Essentially, the steps to reproduce are described in [the issue](facebook#19339):

1. Type some Korean characters in TextInput, such as "하늘" (buttons `ㅎ`,`ㅏ`,`ㄴ`,`ㅡ`,`ㄹ`).
2. Then move the cursor to the beginning of the text, type "파란" (buttons `ㅍ`,`ㅏ`,`ㄹ`,`ㅏ`,`ㄴ`) this time.

**Behaviour before this fix (broken)**
Actual text: `ㅍㅏㄹㅏㄴ하늘`.
Expected text: `파란하늘`.
Characters aren't combined properly.

![ezgif com-resize](https://user-images.githubusercontent.com/466427/41613572-4256dda8-73f6-11e8-99a9-0ab833202b95.gif)

**Behaviour after this fix (correct)**
Actual text: `파란하늘`.
Expected text: `파란하늘`.
Characters are combined, the same behaviour is in vanilla iOS `UITextView`.

![input-with-fix](https://user-images.githubusercontent.com/466427/41613526-1aae2284-73f6-11e8-87f2-c1cef51cd83a.gif)

<!--
  Does this PR require a documentation change?
  Create a PR at https://github.com/facebook/react-native-website and add a link to it here.
-->

<!--
  Required.
  Help reviewers and the release process by writing your own release notes. See below for an example.
-->

[IOS] [BUGFIX] [TextView] - Fix Korean/Chinese/Japanese input for multiline TextView on iOS.

<!--
  **INTERNAL and MINOR tagged notes will not be included in the next version's final release notes.**

    CATEGORY
  [----------]      TYPE
  [ CLI      ] [-------------]    LOCATION
  [ DOCS     ] [ BREAKING    ] [-------------]
  [ GENERAL  ] [ BUGFIX      ] [ {Component} ]
  [ INTERNAL ] [ ENHANCEMENT ] [ {Filename}  ]
  [ IOS      ] [ FEATURE     ] [ {Directory} ]   |-----------|
  [ ANDROID  ] [ MINOR       ] [ {Framework} ] - | {Message} |
  [----------] [-------------] [-------------]   |-----------|

 EXAMPLES:

 [IOS] [BREAKING] [FlatList] - Change a thing that breaks other things
 [ANDROID] [BUGFIX] [TextInput] - Did a thing to TextInput
 [CLI] [FEATURE] [local-cli/info/info.js] - CLI easier to do things with
 [DOCS] [BUGFIX] [GettingStarted.md] - Accidentally a thing/word
 [GENERAL] [ENHANCEMENT] [Yoga] - Added new yoga thing/position
 [INTERNAL] [FEATURE] [./scripts] - Added thing to script that nobody will see
-->
Pull Request resolved: facebook#19809

Differential Revision: D13326614

Pulled By: shergin

fbshipit-source-id: 6a5cab3f7290f0f623a6f4c29353a573eb321b0b
facebook-github-bot pushed a commit that referenced this pull request Feb 10, 2022
Summary:
<!-- Explain the **motivation** for making this change. What existing problem does the pull request solve? -->

Fix #32503

Updating the attributed text in TextView/TextField while inputting Korean language will break input mechanism of the Korean alphabet. This results unexpected text input.

This PR supersedes the previous fixes: #19809, #22546

## Changelog

<!-- Help reviewers and the release process by writing your own changelog entry. For an example, see:
https://github.com/facebook/react-native/wiki/Changelog
-->

[iOS] [Fixed] - Fix a broken input for the Korean alphabet in TextInput

Pull Request resolved: #32523

Test Plan: https://user-images.githubusercontent.com/20317121/140013434-1674c391-54d6-4410-b4c1-c633697e639d.mov

Reviewed By: lunaleaps, sammy-SC

Differential Revision: D32470543

Pulled By: philIip

fbshipit-source-id: e7e34bd362fa2ab2ca579103db01ad8d1a891c35
ShikaSD pushed a commit that referenced this pull request Feb 22, 2022
Summary:
<!-- Explain the **motivation** for making this change. What existing problem does the pull request solve? -->

Fix #32503

Updating the attributed text in TextView/TextField while inputting Korean language will break input mechanism of the Korean alphabet. This results unexpected text input.

This PR supersedes the previous fixes: #19809, #22546

## Changelog

<!-- Help reviewers and the release process by writing your own changelog entry. For an example, see:
https://github.com/facebook/react-native/wiki/Changelog
-->

[iOS] [Fixed] - Fix a broken input for the Korean alphabet in TextInput

Pull Request resolved: #32523

Test Plan: https://user-images.githubusercontent.com/20317121/140013434-1674c391-54d6-4410-b4c1-c633697e639d.mov

Reviewed By: lunaleaps, sammy-SC

Differential Revision: D32470543

Pulled By: philIip

fbshipit-source-id: e7e34bd362fa2ab2ca579103db01ad8d1a891c35
ShikaSD pushed a commit that referenced this pull request Feb 24, 2022
Summary:
<!-- Explain the **motivation** for making this change. What existing problem does the pull request solve? -->

Fix #32503

Updating the attributed text in TextView/TextField while inputting Korean language will break input mechanism of the Korean alphabet. This results unexpected text input.

This PR supersedes the previous fixes: #19809, #22546

## Changelog

<!-- Help reviewers and the release process by writing your own changelog entry. For an example, see:
https://github.com/facebook/react-native/wiki/Changelog
-->

[iOS] [Fixed] - Fix a broken input for the Korean alphabet in TextInput

Pull Request resolved: #32523

Test Plan: https://user-images.githubusercontent.com/20317121/140013434-1674c391-54d6-4410-b4c1-c633697e639d.mov

Reviewed By: lunaleaps, sammy-SC

Differential Revision: D32470543

Pulled By: philIip

fbshipit-source-id: e7e34bd362fa2ab2ca579103db01ad8d1a891c35
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Bug CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. Component: TextInput Related to the TextInput component. Merged This PR has been merged. Platform: iOS iOS applications.
Projects
None yet
6 participants