UITextView — это многострочный текстовый компонент UIKit, наследующий UIScrollView и поддерживающий редактирование атрибутированного текста с встраиванием ссылок и изображений. По документации Apple Developer (2025), UITextView предоставляет UITextViewDelegate с колбэками textViewDidChange, shouldInteractWithURL и shouldInteractWithTextAttachment для обработки взаимодействий. В отличие от UITextField, UITextView поддерживает прокрутку, текстовые стили через typingAttributes и dataDetectorTypes для автоопределения ссылок, адресов и дат. Это основной компонент для отображения контента и ввода многострочного текста в iOS приложениях.
Главное
UITextView — это компонент UIKit, предназначенный для отображения и редактирования многострочного текста. В отличие от UILabel, UITextView поддерживает выделение текста, редактирование, прокрутку при превышении размеров и атрибутированный текст. Будучи наследником UIScrollView, UITextView автоматически включает вертикальную и горизонтальную прокрутку при превышении контента — это настраивается через isScrollEnabled. Класс поддерживает редактирование через свойство isEditable: установите false для read-only режима просмотра. UITextView работает с NSLayoutManager через систему TextKit: NSTextStorage (хранение атрибутированного текста) → NSLayoutManager (разметка строк) → NSTextContainer (геометрия области текста). Эта архитектура позволяет создавать кастомную вёрстку с обтеканием изображений, много-колоночный текст и сложные текстовые макеты. UITextView используется для отображения статей, описаний, логов, комментариев и любых многострочных текстов в iOS.
Разница между UITextView и UITextField выходит далеко за рамки количества строк. UITextField — однострочный UIControl с поддержкой placeholder, left/right view и clear button. UITextView — многострочный UIScrollView с полноценной системой TextKit для атрибутированного текста. UITextField не поддерживает NSAttributedString на уровне отображения (только через attributedText с ограничениями), UITextView обрабатывает NSAttributedString полностью с разными шрифтами, параграф-стайлами и встроенными изображениями. UITextField имеет встроенную кнопку очистки (clearButtonMode), UITextView её не имеет — требуется кастомная реализация. UITextField автоматически меняет свой размер под контент (intrinsicContentSize), UITextView требует ручного управления высотой через contentSize наблюдение или Auto Layout constraint. UITextView поддерживает dataDetectorTypes (автоопределение ссылок), UITextField поддерживает его с iOS 16+. Для ввода многострочного текста (комментарии, заметки, сообщения) выбирайте UITextView. Для полей формы (имя, email, пароль) используйте UITextField.
| Возможность | UITextView | UITextField |
|---|---|---|
| Строки | Многострочный | Однострочный |
| Placeholder | Нет (кастомный) | Встроенный |
| Атрибуты текста | Полный NSAttributedString | Ограниченный |
| Data Detectors | Полная поддержка | iOS 16+ |
| Изображения inline | Через NSTextAttachment | Не поддерживается |
| Прокрутка | Встроенная (UIScrollView) | Нет |
| Left/Right View | Нет | Встроенные |
NSAttributedString — это фундаментальная возможность UITextView, отличающая его от UITextField и UILabel. Атрибутированная строка позволяет задавать разные шрифты, цвета, межстрочные интервалы, выравнивание и ссылки в рамках одного текста. Свойства: textView.attributedText = attributedString. Ключевые атрибуты NSAttributedString.Key: font (.systemFont, .boldSystemFont, кастомный UIFont), foregroundColor, backgroundColor, paragraphStyle (NSMutableParagraphStyle с lineSpacing, alignment, lineBreakMode), link (URL для интерактивных ссылок), underlineStyle, strikethroughStyle, shadow, baselineOffset, kern (межбуквенный интервал). Для создания attributedString используйте init(string:, attributes:) или NSMutableAttributedString для добавления атрибутов к разным диапазонам. UITextView автоматически отображает ссылки (link attribute) как интерактивные — при нажатии вызывается делегатный метод shouldInteractWithURL. Для сброса атрибутов для нового ввода используйте typingAttributes.
import UIKit
let textView = UITextView()
textView.isEditable = false
textView.isScrollEnabled = true
textView.dataDetectorTypes = [.link, .phoneNumber]
let attributedString = NSMutableAttributedString(
string: "Visit our website or call +1-800-555-0199"
)
attributedString.addAttributes([
.font: UIFont.systemFont(ofSize: 16),
.foregroundColor: UIColor.label,
], range: NSRange(location: 0, length: 11))
let linkRange = (attributedString.string as NSString)
.range(of: "website")
attributedString.addAttributes([
.link: URL(string: "https://example.com")!,
.foregroundColor: UIColor.systemBlue,
], range: linkRange)
textView.attributedText = attributedString
UITextViewDelegate — это протокол, управляющий редактированием и взаимодействием с текстом. Основные методы: textViewDidBeginEditing(textView) — вызывается при старте редактирования; textViewDidEndEditing — при завершении; textViewDidChange — при каждом изменении текста; textViewDidChangeSelection — при изменении выделения; textViewShouldInteractWithURL — при нажатии на ссылку (возвращает Bool, разрешён ли переход); textViewShouldInteractWithTextAttachment — при нажатии на встроенное изображение. Для обработки ссылок внутри UITextView переопределите shouldInteractWithURL — в нём можно: открыть URL в SFSafariViewController, показать UIAlertController для подтверждения, обработать кастомные URL schemes. Важно: если textView.isEditable = true, ссылки становятся недоступными для нажатия до двойного тапа — для интерактивных ссылок при редактировании используйте gesture recognizers.
SFSafariViewController — стандартный способ открытия ссылок в iOS приложениях. В методе shouldInteractWithURL создайте SFSafariViewController с URL и представьте его модально или через navigationController. Для универсальных ссылок используйте UIApplication.shared.open(url, options) — но это выходит за пределы приложения. Для запрета открытия ссылок верните false в shouldInteractWithURL и обработайте URL самостоятельно.
NSTextContainer — часть архитектуры TextKit, определяющая геометрическую область, в которой отображается текст UITextView. Каждый UITextView имеет стандартный textContainer, настраиваемый через: textView.textContainerInset — отступы текста от границ textView (UIEdgeInsets); textView.textContainer.lineFragmentPadding — горизонтальный отступ внутри каждой строки; textView.textContainer.maximumNumberOfLines — ограничение количества строк (0 = без лимита); textView.textContainer.exclusionPaths — массив UIBezierPath для областей, которые текст должен обтекать (изображения, кастомные shapes). ExclusionPaths позволяют создавать сложную вёрстку: текст обтекает круглое изображение профиля, иконку или любой произвольный контур. Для динамического размера UITextView наблюдайте contentSize через KVO или делегат и обновляйте constraints.
// Dynamic UITextView height via contentSize
func textViewDidChange(textView: UITextView) {
let fixedWidth = textView.frame.size.width
let newSize = textView.sizeThatFits(
CGSize(width: fixedWidth, height: CGFloat.greatestFiniteMagnitude)
)
heightConstraint.constant = newSize.height
UIView.animate(withDuration: 0.1) {
self.view.layoutIfNeeded()
}
}
// ExclusionPath for image wrapping
let imageFrame = CGRect(x: 16, y: 100, width: 80, height: 80)
let exclusionPath = UIBezierPath(rect: imageFrame)
textView.textContainer.exclusionPaths = [exclusionPath]
dataDetectorTypes — свойство UITextView, которое автоматически распознаёт и делает интерактивными определённые типы данных в тексте: .link (URL, email), .phoneNumber (телефонные номера), .address (адреса), .calendarEvent (даты и события), .flightNumber (номера рейсов), .lookupSuggestion (поисковые подсказки), .trackingNumber (трекинг-номера), .money (суммы), .shipmentTrackingNumber, .all (все типы). Data Detector работает с NSDataDetector и URL, автоматически подсвечивая обнаруженные данные. Для кастомизации обработки установите dataDetectorTypes и переопределите shouldInteractWithURL в делегате. Важно: dataDetectorTypes работает только для URL и phoneNumber без дополнительной настройки — остальные типы могут требовать iOS 16+. Data Detector не конфликтует с link attribute в NSAttributedString — оба механизма работают параллельно. Для read-only UITextView с контентом (новости, статьи) установите dataDetectorTypes = [.link, .phoneNumber].
Рассмотрим два практических примера использования UITextView в iOS приложениях. Первый — read-only text view с атрибутированным текстом и data detector для отображения контента. Второй — редактируемый text view с ленивым placeholder и динамической высотой для формы комментария. Оба примера используют best practices UIKit: делегатный протокол, Auto Layout и TextKit.
Read-only режим включается установкой isEditable = false и isSelectable = true. Это позволяет пользователю выделять текст и нажимать на ссылки, но не редактировать. Установите dataDetectorTypes для автоопределения ссылок, backgroundColor = .clear для прозрачного фона. Для отображения длинного контента используйте attributedText с NSMutableParagraphStyle lineSpacing для читаемости. Добавьте link attributes для ключевых ссылок внутри текста.
import UIKit
class ArticleViewController: UIViewController {
let contentView = UITextView()
override func viewDidLoad() {
super.viewDidLoad()
contentView.isEditable = false
contentView.isSelectable = true
contentView.dataDetectorTypes = [.link, .phoneNumber]
contentView.backgroundColor = .clear
contentView.textContainerInset = UIEdgeInsets(
top: 8, left: 16,
bottom: 8, right: 16
)
contentView.delegate = self
loadArticleContent()
}
func loadArticleContent() {
guard let url = URL(string: "https://example.com/article")
else { return }
// Load content from URL and set attributedText
}
}
Placeholder для UITextView не встроен — реализуйте его через UILabel поверх textView или через attributedText с проверкой isEmpty. Простой подход: UILabel с серым текстом, который скрывается при начале редактирования. В textViewDidChange проверяйте наличие текста и скрывайте/показывайте placeholder. Для более элегантного решения используйте свойство typingAttributes для установки цвета вводимого текста. Динамическая высота textView достигается через наблюдение contentSize и обновление constraints — это стандартный паттерн для чатов и форм комментариев.
Часто задаваемые вопросы
UITextView не имеет встроенного placeholder. Стандартное решение: добавьте UILabel с серым текстом поверх textView. В textViewDidBeginEditing скрывайте label, в textViewDidEndEditing показывайте, если текст пуст. Альтернативно: используйте attributedText с серым цветом как placeholder и сбрасывайте при начале редактирования. Для готового решения используйте библиотеку KMPlaceholderTextView или ReactorKit.
Установите textContainerInset = .zero и lineFragmentPadding = 0: textView.textContainerInset = UIEdgeInsets.zero; textView.textContainer.lineFragmentPadding = 0. Дополнительно: textView.contentInset = .zero. Это полностью удалит отступы от краёв textView до текста. Учтите, что lineFragmentPadding по умолчанию равен 5.
Проверьте: isSelectable = true (необходимо для взаимодействия), dataDetectorTypes включает .link, делегат не возвращает false в shouldInteractWithURL. Если textView.isEditable = true, ссылки недоступны для одноразового нажатия — требуется двойной тап. Для интерактивных ссылок в редактируемом textView добавьте UITapGestureRecognizer поверх textView и обрабатывайте URL вручную.
Установите isScrollEnabled = true и добавьте height constraint с фиксированным значением. Текст, превышающий высоту, будет прокручиваться. Для оптимального UX используйте maxHeight: наблюдайте contentSize и устанавливайте height constraint не выше maxHeight. При превышении maxHeight включайте scrollEnabled. Это стандартный паттерн для полей ввода сообщений и комментариев.
Используйте NSTextAttachment: создайте объект, установите image и bounds, затем создайте NSAttributedString из attachment и вставьте в textView.attributedText. Пример: let attachment = NSTextAttachment(); attachment.image = image; attachment.bounds = CGRect(x, y, width, height); let attributedString = NSAttributedString(attachment: attachment). Изображение отобразится inline в тексте и будет прокручиваться вместе с ним.
Итоги
Мы разработаем мобильное приложение под ключ
IT Sectr создаёт приложения для iOS и Android для стартапов и бизнеса с 2017 года. Мы проконсультируем вас и предложим наилучшее решение.
Читайте также