We have submitted a feedback for this issue: FB21230723
We're building a note-taking app for iOS and macOS that uses both UITextView and NSTextView.
When performing text input that involves a marked range (such as Japanese input) in a UITextView or NSTextView with a UITextViewDelegate or NSTextViewDelegate set, the text view's marked range (markedTextRange / markedRange()) has not yet been updated at the moment when shouldChangeTextIn is invoked.
UITextViewDelegate.textView(_:shouldChangeTextIn:replacementText:)NSTextViewDelegate.textView(_:shouldChangeTextIn:replacementString:)
The current behavior is this when entering text in Japanese: (same for NSTextView)
func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
print(textView.markedTextRange != nil) // prints out false
DispatchQueue.main.async {
print(textView.markedTextRange != nil) // prints out true
}
}
However, we need the value of markedTextRange right away in order to determine whether to return true or false from this method.
Is there any workaround for this issue?
It seems that iOS does update markedTextRange for me. I tried the following code:
func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
if let markedTextRange = textView.markedTextRange {
let markedText = textView.text(in: markedTextRange) ?? ""
print("markedText = \(markedText), replacementText = \(text)")
} else {
print("replacementText = \(text)")
}
return true
}
And get the following result when inputting "あ" and then "か" with Japanese Kana input method:
replacementText = あ
markedText = あ, replacementText = か
Do you see the same thing? is markedText + replacementText not enough for you to determine whether the input is valid?
I tested with iPhone + iOS 26.1(23B85), if that matters.
Best,
——
Ziqiao Chen
Worldwide Developer Relations.