Limit number of characters in uitextview
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
To limit the number of characters in a UITextView, intercept edits through the delegate and decide whether the proposed change should be accepted. The key detail is that you must compute the resulting text after the edit, not just check the current text length.
Use shouldChangeTextIn in the Delegate
The standard place to enforce a limit is the delegate method textView(_:shouldChangeTextIn:replacementText:).
This handles typing, deletion, and replacement in one place.
Why Range Conversion Matters
UITextView gives you an NSRange, but Swift strings are Unicode-aware. Converting the range properly is important, especially when the text contains emoji or other multi-scalar characters.
That is why the Range(range, in: current) conversion is safer than trying to slice by integer offsets manually.
Update a Counter Label at the Same Time
In real apps, users usually benefit from a remaining-character counter.
The delegate check enforces the rule, and the counter makes the rule visible.
Be Careful With Pasting and Marked Text
Character limits are not only about keyboard typing. Pasting large text can exceed the limit in one action, so the delegate check must handle replacement text of any size.
If you support complex input methods, also remember that temporary marked text during composition can make editing behavior more subtle. Test with real keyboards and languages, not only with simple Latin typing.
If You Need Truncation Instead of Rejection
Some apps prefer to accept the paste but truncate the final text.
This is a different user experience from rejecting the change upfront. Use it only if that behavior is intentional.
Decide Whether Hard Blocking or Soft Feedback Is Better
Some apps should block extra input immediately. Others should let the user keep editing temporarily and show a counter or validation message. The technical implementation is different, but the real decision is product behavior rather than delegate syntax alone.
Keep the UX Consistent With Validation Elsewhere
If the same field is also validated on the backend, make sure the frontend character limit matches the server rule. Mismatched limits create confusing bugs where the UI accepts text that the API later rejects, or vice versa.
Test With Real Copy and Paste Behavior
Typing one character at a time is the easy case. Paste operations are where many length-limit implementations show their real behavior, so they should be part of the normal test path.
Common Pitfalls
The biggest mistake is checking only textView.text.count before the edit instead of calculating the post-edit result.
Another issue is forgetting about paste operations, which can add many characters at once.
A third problem is mishandling Unicode by working with raw integer indexes instead of converting the range safely.
Summary
- Use
textView(_:shouldChangeTextIn:replacementText:)to enforce a character limit. - Compute the resulting text after the proposed change, not just the current length.
- Convert
NSRangesafely into a Swift string range. - Test with paste operations and non-trivial Unicode input.
- Pair the limit with a visible counter when user experience matters.

