Mastering UITextView: Advanced Text Editing in iOS Apps
UITextView is a powerful UIKit component for displaying and editing multi-line text with scrolling capabilities. Beyond simple text entry, it offers extensive customization for rich text, data detection, and intricate user interactions. This article delves into its advanced features, helping you create sophisticated text experiences in your iOS apps.

Introduction to UITextView: Beyond the Basics
UITextView is a fundamental UIKit class designed for displaying and editing blocks of text that can span multiple lines. Unlike UILabel, which is static, or UITextField, which is typically for single-line input, UITextView provides a scrollable view for extensive content. It's a key component for applications requiring rich text editing, notes, chat interfaces, or any scenario where users interact with large amounts of text.
While dragging a UITextView from the Object Library in Xcode and setting its basic properties like text and font is straightforward, its true power lies in its advanced configurations and delegate methods. You can customize its appearance, enable data detection, manage user input, and even integrate rich text formatting using NSAttributedString.
Core Capabilities:
- Multi-line Text: Easily handles text that wraps and scrolls.
- Editable or Read-Only: Control whether the user can modify the text.
- Rich Text Support: Display styled text using
NSAttributedString. - Data Detection: Automatically highlight phone numbers, URLs, addresses, and more.
- Scrollability: Inherits scrolling behavior from UIScrollView, allowing content to extend beyond its bounds.
- Delegate Methods: Fine-grained control over editing events, selections, and content changes.
Let's start by looking at a basic setup and then dive into more advanced functionalities.
Handling User Input and Delegates
To effectively interact with and manage UITextView, you'll primarily use its delegate. The UITextViewDelegate protocol provides a suite of methods that notify your app about changes in the text, editing status, and user interactions. This allows you to implement custom validation, character limits, or dynamic UI updates.
Key UITextViewDelegate Methods:
textViewShouldBeginEditing(_:): Asks the delegate if editing should begin in the specified text view.textViewDidBeginEditing(_:): Tells the delegate that editing an object has begun.textViewShouldEndEditing(_:): Asks the delegate if editing should stop in the specified text view.textViewDidEndEditing(_:): Tells the delegate that editing of the specified text view has ended.textView(_:shouldChangeTextIn:replacementText:): Asks the delegate if the specified text should be replaced in the text view. This is crucial for implementing real-time input validation, character limits, or filtering inappropriate words.textViewDidChange(_:): Tells the delegate that the text in the specified text view has changed. Ideal for updating character counts or enabling/disabling UI elements based on text content.textViewDidChangeSelection(_:): Tells the delegate that the text selection has changed.
To become a delegate, your class must conform to UITextViewDelegate and you must set the textView.delegate property. Let's see how to implement a character limit and respond to text changes.
Rich Text and Data Detection
One of UITextView's most powerful features is its support for NSAttributedString for rich text formatting. This allows you to apply different fonts, colors, styles (bold, italic), and even embed attachments within the text. You can also configure UITextView to automatically detect specific types of data, like phone numbers, links, and addresses, making them tappable.
NSAttributedString for Styling:
To use NSAttributedString, you typically create an instance and apply attributes to specific ranges of text. Common attributes include NSAttributedString.Key.font, NSAttributedString.Key.foregroundColor, NSAttributedString.Key.backgroundColor, and more. This gives you fine-grained control over the appearance of your text.
Data Detectors:
UITextView offers built-in data detection capabilities through the dataDetectorTypes property. This property accepts an UIDataDetectorTypes option set, allowing you to specify what kind of information UITextView should automatically recognize and make interactive. Available types include:
.phoneNumber.link.address.calendarEvent.flightNumber(Available from iOS 17.0).trackingNumber(Available from iOS 17.0).spotlightSuggestion(Available from iOS 17.0).all
When data detectors are enabled, the detected elements are typically styled as links and can be tapped by the user to perform the associated action (e.g., open a URL in Safari, call a phone number). This significantly enhances user experience for text-heavy content.
Compatibility Note: UIDataDetectorTypes.flightNumber, UIDataDetectorTypes.trackingNumber, and UIDataDetectorTypes.spotlightSuggestion are available to iOS 17.0 and later.
Managing Keyboard and First Responder Status
When working with UITextView (or any text input control), managing the keyboard is a critical aspect of user experience. You need to ensure the keyboard appears when expected, dismisses when no longer needed, and doesn't obstruct the text input area.
Becoming and Resigning First Responder:
becomeFirstResponder(): This method makes theUITextViewthe 'first responder,' which means it's ready to receive touch events, and the keyboard will automatically appear. You typically call this when you want the user to start typing immediately, e.g., when a chat view loads.resignFirstResponder(): This method forces theUITextViewto relinquish its first responder status, causing the keyboard to dismiss. You might call this when the user taps a 'Done' button, taps outside the text view, or when navigating away from the input screen.
Adjusting Content for the Keyboard:
A common challenge is when the keyboard covers the UITextView. You can address this by observing keyboard notifications and adjusting the UITextView's contentInset or the scroll view content offset, especially if your UITextView is embedded in a larger scrollable area.
Keyboard Notifications:
UIResponder.keyboardWillShowNotificationUIResponder.keyboardWillHideNotificationUIResponder.keyboardWillChangeFrameNotification
By observing these notifications, you can get the keyboard's frame and animation duration, allowing you to smoothly animate adjustments to your UI. This is a robust way to handle keyboard obstructions. While Swift UI offers built-in ignoresSafeArea(.keyboard), in UIKit, you perform this manually.
Compatibility Note: Keyboard notifications are available from iOS 2.0+.
Best Practices for UITextView
To ensure your UITextView implementations are robust, performant, and user-friendly, consider the following best practices:
-
Memory Management for Large Text: If you're displaying extremely large amounts of text, be mindful of performance.
NSAttributedStringcan consume more memory than plain strings. For very long, static text, consider rendering it as aUILabel(withnumberOfLines = 0) if editing isn't required, or lazy-loading content. -
Accessibility (VoiceOver): Ensure your
UITextViewis accessible. VoiceOver users should be able to hear the content and be informed of its editable state.isEditableandaccessibilityLabelare key properties. If you use a placeholder text pattern (like in theTextViewDelegateViewControllerexample), make sure VoiceOver doesn't read it when the text field is active and empty. -
Keyboard Avoidance: Always implement proper keyboard avoidance logic. While the example above uses simple constant adjustments, for complex layouts, you might need a more sophisticated solution, perhaps by embedding the
UITextViewin aUIScrollViewand adjusting itscontentInset. -
Placeholder Text: For empty
UITextViews, consider using a 'placeholder' by setting the to and the actual to instructional text when editing hasn't begun, then clearing it on . (As shown in the example).
By following these guidelines, you can leverage UITextView to its fullest potential, providing a superior text editing experience in your iOS applications.
Common Interview Questions
How do I add a placeholder to UITextView, similar to UITextField?
Unlike UITextField, UITextView doesn't have a direct `placeholder` property. You can implement placeholder behavior using the `UITextViewDelegate` methods. Set initial `text` and `textColor` to a placeholder string and light gray color. Then, in `textViewDidBeginEditing`, clear the text and set the color to black. In `textViewDidEndEditing`, if the text is empty, reset it to the placeholder. See the `TextViewDelegateViewController` example for a practical implementation.
How can I limit the number of characters a user can type into a UITextView?
To enforce a character limit, implement the `textView(_:shouldChangeTextIn:replacementText:)` delegate method. Inside this method, calculate the new length of the text by replacing the characters in the specified range. If the `updatedText.count` exceeds your maximum limit, return `false` to prevent the change; otherwise, return `true`. You can also update a character count label in `textViewDidChange(_:)` to provide real-time feedback.
What's the best way to handle the keyboard blocking my UITextView without using an external library?
The most robust way to handle keyboard obstruction in UIKit is to observe keyboard notifications (`UIResponder.keyboardWillShowNotification` and `UIResponder.keyboardWillHideNotification`). When the keyboard appears, get its frame and animation duration from the notification's `userInfo` dictionary. Then, adjust the bottom constraint of your `UITextView` (or its containing view/scroll view's `contentInset`) by the keyboard's height, animating the change over the same duration. When the keyboard hides, reset the constraints or `contentInset` to their original values.