UITextView è un componente di testo multilinea di UIKit, erede di UIScrollView che supporta la modifica di testo attribuito con incorporamento di link e immagini. Secondo la documentazione Apple Developer (2025), UITextView fornisce UITextViewDelegate con callback textViewDidChange, shouldInteractWithURL e shouldInteractWithTextAttachment per la gestione delle interazioni. A differenza di UITextField, UITextView supporta lo scorrimento, gli stili di testo tramite typingAttributes e dataDetectorTypes per il rilevamento automatico di link, indirizzi e date. Questo è il componente principale per visualizzare contenuti e inserire testo multilinea nelle applicazioni iOS.
Punti Chiave
UITextView è un componente UIKit progettato per visualizzare e modificare testo multilinea. A differenza di UILabel, UITextView supporta la selezione del testo, la modifica, lo scorrimento quando il contenuto supera le dimensioni e il testo attribuito. Essendo una sottoclasse di UIScrollView, UITextView include automaticamente lo scorrimento verticale e orizzontale quando il contenuto eccede — questo si configura tramite isScrollEnabled. La classe supporta la modifica tramite la proprietà isEditable: impostare su false per la modalità sola lettura. UITextView funziona con NSLayoutManager attraverso il sistema TextKit: NSTextStorage (archiviazione del testo attribuito) → NSLayoutManager (layout delle righe) → NSTextContainer (geometria dell'area di testo). Questa architettura consente layout personalizzati con avvolgimento delle immagini, testo multi-colonna e layout di testo complessi. UITextView viene utilizzato per visualizzare articoli, descrizioni, log, commenti e qualsiasi testo multilinea in iOS.
La differenza tra UITextView e UITextField va ben oltre il numero di righe. UITextField è un UIControl a riga singola con supporto placeholder, viste sinistra/destra e pulsante di cancellazione. UITextView è un UIScrollView multilinea con un sistema TextKit completo per testo attribuito. UITextField non supporta NSAttributedString a livello di visualizzazione (solo tramite attributedText con limitazioni), UITextView gestisce NSAttributedString completamente con diversi font, stili di paragrafo e immagini incorporate. UITextField ha un pulsante di cancellazione integrato (clearButtonMode), UITextView no — è necessaria un'implementazione personalizzata. UITextField si ridimensiona automaticamente al contenuto (intrinsicContentSize), UITextView richiede una gestione manuale dell'altezza tramite osservazione di contentSize o vincoli Auto Layout. UITextView supporta dataDetectorTypes (rilevamento automatico dei link), UITextField lo supporta da iOS 16+. Per l'input di testo multilinea (commenti, note, messaggi) scegliere UITextView. Per i campi del modulo (nome, email, password) utilizzare UITextField.
| Caratteristica | UITextView | UITextField |
|---|---|---|
| Righe | Multilinea | Riga singola |
| Placeholder | No (personalizzato) | Integrato |
| Attributi testo | NSAttributedString completo | Limitato |
| Data Detectors | Supporto completo | iOS 16+ |
| Immagini inline | Tramite NSTextAttachment | Non supportato |
| Scorrimento | Integrato (UIScrollView) | No |
| Vista Sin./Des. | No | Integrata |
NSAttributedString è una capacità fondamentale di UITextView che lo distingue da UITextField e UILabel. Una stringa attribuita consente di impostare diversi font, colori, interlinea, allineamento e link all'interno di un unico testo. Proprietà: textView.attributedText = attributedString. Attributi chiave di NSAttributedString.Key: font (.systemFont, .boldSystemFont, UIFont personalizzato), foregroundColor, backgroundColor, paragraphStyle (NSMutableParagraphStyle con lineSpacing, alignment, lineBreakMode), link (URL per link interattivi), underlineStyle, strikethroughStyle, shadow, baselineOffset, kern (spaziatura tra caratteri). Per creare un attributedString utilizzare init(string:, attributes:) o NSMutableAttributedString per aggiungere attributi a intervalli diversi. UITextView visualizza automaticamente i link (attributo link) come interattivi — premendoli si attiva il metodo delegato shouldInteractWithURL. Per reimpostare gli attributi per un nuovo input utilizzare 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 è un protocollo che gestisce la modifica e l'interazione con il testo. Metodi principali: textViewDidBeginEditing(textView) — chiamato all'inizio della modifica; textViewDidEndEditing — al termine della modifica; textViewDidChange — ad ogni modifica del testo; textViewDidChangeSelection — quando cambia la selezione; textViewShouldInteractWithURL — quando si tocca un link (restituisce Bool, consente la transizione); textViewShouldInteractWithTextAttachment — quando si tocca un'immagine incorporata. Per gestire i link all'interno di UITextView sovrascrivere shouldInteractWithURL — al suo interno è possibile: aprire URL in SFSafariViewController, mostrare UIAlertController per conferma, gestire schemi URL personalizzati. Importante: se textView.isEditable = true, i link non sono disponibili per un singolo tocco — è necessario il doppio tocco. Per link interattivi in textView modificabile utilizzare gesture recognizers.
SFSafariViewController è il modo standard per aprire i link nelle applicazioni iOS. Nel metodo shouldInteractWithURL creare SFSafariViewController con l'URL e presentarlo modalmente o tramite navigationController. Per i link universali utilizzare UIApplication.shared.open(url, options) — ma questo esce dall'applicazione. Per impedire l'apertura dei link restituire false in shouldInteractWithURL e gestire l'URL manualmente.
NSTextContainer fa parte dell'architettura TextKit, definendo l'area geometrica in cui viene visualizzato il testo di UITextView. Ogni UITextView ha un textContainer standard, configurabile tramite: textView.textContainerInset — margini del testo dai bordi del textView (UIEdgeInsets); textView.textContainer.lineFragmentPadding — riempimento orizzontale all'interno di ogni riga; textView.textContainer.maximumNumberOfLines — limite di righe (0 = senza limite); textView.textContainer.exclusionPaths — array di UIBezierPath per aree che il testo deve contornare (immagini, forme personalizzate). ExclusionPaths consentono layout complessi: il testo contorna un'immagine del profilo circolare, un'icona o qualsiasi forma arbitraria. Per l'altezza dinamica di UITextView osservare contentSize tramite KVO o delegato e aggiornare i vincoli.
// 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 è una proprietà di UITextView che riconosce automaticamente e rende interattivi determinati tipi di dati nel testo: .link (URL, email), .phoneNumber (numeri di telefono), .address (indirizzi), .calendarEvent (date ed eventi), .flightNumber (numeri di volo), .lookupSuggestion (suggerimenti di ricerca), .trackingNumber (numeri di tracciamento), .money (importi), .shipmentTrackingNumber, .all (tutti i tipi). Data Detector funziona con NSDataDetector e URL, evidenziando automaticamente i dati rilevati. Per personalizzare la gestione impostare dataDetectorTypes e sovrascrivere shouldInteractWithURL nel delegato. Importante: dataDetectorTypes funziona solo per URL e phoneNumber senza configurazione aggiuntiva — altri tipi potrebbero richiedere iOS 16+. Data Detector non entra in conflitto con l'attributo link in NSAttributedString — entrambi i meccanismi funzionano in parallelo. Per UITextView in sola lettura con contenuto (notizie, articoli) impostare dataDetectorTypes = [.link, .phoneNumber].
Consideriamo due esempi pratici di utilizzo di UITextView nelle applicazioni iOS. Il primo — una vista testo in sola lettura con testo attribuito e rilevatore di dati per visualizzare contenuti. Il secondo — una vista testo modificabile con placeholder pigro e altezza dinamica per un modulo di commento. Entrambi gli esempi utilizzano le migliori pratiche di UIKit: protocollo delegato, Auto Layout e TextKit.
La modalità sola lettura viene attivata impostando isEditable = false e isSelectable = true. Ciò consente all'utente di selezionare il testo e toccare i link, ma non di modificare. Impostare dataDetectorTypes per il rilevamento automatico dei link, backgroundColor = .clear per sfondo trasparente. Per contenuti lunghi utilizzare attributedText con NSMutableParagraphStyle lineSpacing per la leggibilità. Aggiungere attributi link per i link chiave all'interno del testo.
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
}
}
Il Placeholder per UITextView non è integrato — implementarlo tramite un UILabel sopra il textView o tramite attributedText con controllo isEmpty. Un approccio semplice: un UILabel con testo grigio che si nasconde all'inizio della modifica. In textViewDidChange verificare la presenza di testo e nascondere/mostrare il placeholder. Per una soluzione più elegante utilizzare la proprietà typingAttributes per impostare il colore del testo di input. L'altezza dinamica del textView si ottiene osservando contentSize e aggiornando i vincoli — questo è un modello standard per chat e moduli di commento.
Domande Frequenti
UITextView non ha un placeholder integrato. La soluzione standard: aggiungere un UILabel con testo grigio sopra il textView. In textViewDidBeginEditing nascondere l'etichetta, in textViewDidEndEditing mostrarla se il testo è vuoto. In alternativa: utilizzare attributedText con colore grigio come placeholder e reimpostarlo all'inizio della modifica. Per una soluzione pronta all'uso, utilizzare la libreria KMPlaceholderTextView o ReactorKit.
Impostare textContainerInset = .zero e lineFragmentPadding = 0: textView.textContainerInset = UIEdgeInsets.zero; textView.textContainer.lineFragmentPadding = 0. Inoltre: textView.contentInset = .zero. Questo rimuoverà completamente i margini dai bordi del textView al testo. Notare che lineFragmentPadding predefinito è 5.
Verificare: isSelectable = true (necessario per l'interazione), dataDetectorTypes include .link, il delegato non restituisce false in shouldInteractWithURL. Se textView.isEditable = true, i link non sono disponibili per un singolo tocco — è necessario il doppio tocco. Per link interattivi in textView modificabile aggiungere UITapGestureRecognizer sopra il textView e gestire gli URL manualmente.
Impostare isScrollEnabled = true e aggiungere un vincolo di altezza con un valore fisso. Il testo che supera l'altezza scorrerà. Per un'UX ottimale utilizzare maxHeight: osservare contentSize e impostare il vincolo di altezza non superiore a maxHeight. Quando si supera maxHeight, abilitare scrollEnabled. Questo è un modello standard per campi di input di messaggi e commenti.
Utilizzare NSTextAttachment: creare un oggetto, impostare l'immagine e i bounds, quindi creare un NSAttributedString dall'allegato e inserirlo in textView.attributedText. Esempio: let attachment = NSTextAttachment(); attachment.image = image; attachment.bounds = CGRect(x, y, width, height); let attributedString = NSAttributedString(attachment: attachment). L'immagine verrà visualizzata inline nel testo e scorrerà con esso.
Riepilogo
Svilupperemo un'applicazione mobile chiavi in mano
IT Sectr crea applicazioni iOS e Android per startup e aziende dal 2017. Ti consulteremo e ti proporremo la soluzione migliore.
Leggi anche