Rxswift: UITextView.rx_text doesn't catch iOS autocorrect text changes

Created on 11 Dec 2015  Â·  13Comments  Â·  Source: ReactiveX/RxSwift

UITextView.rx_text observes text changes via textViewDidChange. Unfortunately, when text changes due to iOS autocorrect, the textViewDidChange is not called, therefore rx_text never receives that new text.

You can test it by creating a text view, make sure autocorrection is enabled, observe rx_text, type a misspelled word and move focus away from the text view. The text will be automatically corrected, but the last change will never be observed via rx_text, because textViewDidChange doesn't fire when autocorrect happens.

bug

All 13 comments

Hi @timojaask ,

I've confirmed the problem. This is the only way I know how to solve this, but I don't like it.

https://github.com/ReactiveX/RxSwift/commit/e14ca2e94d4e995c552c2d7c417f52ad9c3b75d7

Any ideas how to solve this more elegantly?

Hi, guys
@kzaher how about rx_observeWeakly of text keypath

Hi @sergdort ,

that's an interesting idea :) I've just tried it, and unfortunately it doesn't seem to work either :/

Also NSNotificationCenter.defaultCenter().rx_notification(UITextViewTextDidChangeNotification, object:self) doesn't fire in that case.

Is there some obvious API I'm missing?

Just looked at how ReactiveCocoa did this, looks like they did the same and probable they also have bug =)

Haha, yeah, I've also checked other reactive/binding frameworks :)

This hack is the best thing I could conjure so far. ¯_(ツ)_/¯
This does look like a bug in UITextView, but this is a pretty ugly one and would like to find some workaround.

How about observe textViewDidEndEditing instead of func textView(textView: UITextView, shouldChangeTextInRange range: NSRange, replacementText text: String) -> Bool

Looks like this bug appears only when you moving focus away from the text view

Yeah, that also appears to be working ...

I'm wondering is there any other edge case like this one what textViewDidEndEditing: can't catch ...

Maybe we can use textViewDidEndEditing: and I can just implement @objc public func textView(textView: UITextView, shouldChangeTextInRange range: NSRange, replacementText text: String) -> Bool { return true } so that if we need this uglier hack in future, we don't touch public interface ...

Looks like this bug could also appears on UITextField rx_text

There is also NSTextStorageDelegate in textStorage of UITextView
and probably method:

- (void)textStorage:(NSTextStorage *)textStorage didProcessEditing(NSTextStorageEditActions)editedMask range:(NSRange)editedRange changeInLength:(NSInteger)delta

could work too

I have noticed that same behavior on UITextField also. I've also been able to repro this without ending editing :(

I think it's worth a shot to try

- (void)textStorage:(NSTextStorage *)textStorage didProcessEditing(NSTextStorageEditActions)editedMask range:(NSRange)editedRange changeInLength:(NSInteger)delta

... for NSTextView.

I'm still unsure how to solve NSTextField without equivalent ugly hack :/

Hi @kzaher
Have you tried to add proxy target for UIControlEvents UIControlEvents.AllEditingEvents ?

With this setup
self.textField.addTarget(self, action: "textFieldDidChange:", forControlEvents: .AllEditingEvents)

I was able to get all changes of text

Hi @kzaher looks like NSTextStorageDelegate works great, please take a look, may be I did something wrong :)

This is done :)

Was this page helpful?
0 / 5 - 0 ratings

Related issues

acecilia picture acecilia  Â·  3Comments

jaumard picture jaumard  Â·  3Comments

RobinFalko picture RobinFalko  Â·  3Comments

apoloa picture apoloa  Â·  3Comments

delebedev picture delebedev  Â·  3Comments