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

UITextViewDelegate-like functionality? #13

Open
jshier opened this issue Mar 3, 2021 · 3 comments
Open

UITextViewDelegate-like functionality? #13

jshier opened this issue Mar 3, 2021 · 3 comments
Labels
question Further information is requested

Comments

@jshier
Copy link

jshier commented Mar 3, 2021

Question

UITextViewDelegate allows you to control whether the user's edits take effect through textView(_:shouldChangeTextIn:replacementText:). I can find no replacement for TwitterTextEditor. The closest I can find is TextEditorViewEditingContentDelegate's textEditorView(_:updateEditingContent) method, but returning nil from that method doesn't seem to have the affect I want (not applying the change). It seems like I should be able to create my own editing content, but there are no types which publicly conform to TextEditorViewEditingContent. Am I supposed to create my own conforming type? In any case, it seems like this functionality should be simpler.

@jshier
Copy link
Author

jshier commented Mar 3, 2021

Adding my own conforming type seems to work.

extension TextEditor: TextEditorViewEditingContentDelegate {
    func textEditorView(_ textEditorView: TextEditorView,
                        updateEditingContent editingContent: TextEditorViewEditingContent)
        -> TextEditorViewEditingContent? {
        guard editingContent.text.count > maximumCharacterCount else { return editingContent }

        let text = String(editingContent.text.prefix(maximumCharacterCount))

        return EditedContent(text: text,
                             selectedRange: NSRange(location: text.utf16.count, length: 0))
    }
}

private struct EditedContent: TextEditorViewEditingContent {
    var text: String

    var selectedRange: NSRange
}

@niw
Copy link
Contributor

niw commented Mar 4, 2021

Hi, @jshier!

These APIs design is actually intentional.

It’s not documented by Apple, however, textView(_:shouldChangeTextIn:replacementText:) is very problematic API and we actually shouldn’t return false from this delegate method because it will brake many Input Method Program used for eastern Asian languages and some other languages.
This fact is also described in the comment of Twitter Text Editor code (The marked text mentioned in this comment means the one typed by Input Method Program.)
https://github.com/twitter/TwitterTextEditor/blob/master/Sources/TwitterTextEditor/TextEditorView.swift#L1660-L1672

Also replacementText is not always actual replacement text but sometimes faked control characters generated by the keyboard or separated symbols of a part of input characters, that means we can’t use it getting actual text changes.

Therefore, Twitter Text Editor’s textEditorView(_:updateEditingContent) is an alternative to it, which gives you the safe way to do what that problematic delegate provides to you.

And you’re true, we have to add own struct (or class) that conforms TextEditorViewEditingContent. This is mostly because that Twitter Text Editor also provides a simple way to wrap API for Objective-C usage.

By the way, for limiting number of characters, I recommend to not actually limit number of characters by the text editor level, but provides commit action to users such as adding Save or Send button to the interface then decide if application accepts the text or not when these buttons are tapped.
Because users may want to type more and then polish it in regular typing situation, so if it is limited by the number characters, it might be annoying.
Well, it’s just ”in general” for regular user experiences. It might be vary for the application requirements.

@jshier
Copy link
Author

jshier commented Mar 4, 2021

Thanks, good to know I'm on the right track. I certainly understand the difficulties with textView(_:shouldChangeTextIn:replacementText:), which is one of the reasons I'm using TwitterTextEditor (thanks!). You may want to vend a conforming type users can use to customize the response. As it is now, returning the incoming value or nil seem to do the same thing in the delegate method.

By the way, for limiting number of characters, I recommend to not actually limit number of characters by the text editor level, but provides commit action to users such as adding Save or Send button to the interface then decide if application accepts the text or not when these buttons are tapped.
Because users may want to type more and then polish it in regular typing situation, so if it is limited by the number characters, it might be annoying.
Well, it’s just ”in general” for regular user experiences. It might be vary for the application requirements.

That's what I argued for but the requirements went the other way. 😢

@niw niw added the question Further information is requested label Feb 22, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
question Further information is requested
Projects
None yet
Development

No branches or pull requests

2 participants