UITextView est un composant de texte multiligne d'UIKit, héritant d'UIScrollView et prenant en charge l'édition de texte attribué avec incorporation de liens et d'images. Selon la documentation Apple Developer (2025), UITextView fournit UITextViewDelegate avec les callbacks textViewDidChange, shouldInteractWithURL et shouldInteractWithTextAttachment pour la gestion des interactions. Contrairement à UITextField, UITextView prend en charge le défilement, les styles de texte via typingAttributes et dataDetectorTypes pour la détection automatique des liens, adresses et dates. C'est le composant principal pour afficher du contenu et saisir du texte multiligne dans les applications iOS.
Points Clés
UITextView est un composant UIKit conçu pour afficher et éditer du texte multiligne. Contrairement à UILabel, UITextView prend en charge la sélection de texte, l'édition, le défilement lorsque le contenu dépasse la taille et le texte attribué. En tant que sous-classe d'UIScrollView, UITextView inclut automatiquement le défilement vertical et horizontal lorsque le contenu dépasse — cela se configure via isScrollEnabled. La classe prend en charge l'édition via la propriété isEditable : définissez sur false pour le mode lecture seule. UITextView fonctionne avec NSLayoutManager via le système TextKit : NSTextStorage (stockage de texte attribué) → NSLayoutManager (mise en page des lignes) → NSTextContainer (géométrie de la zone de texte). Cette architecture permet des mises en page personnalisées avec habillage d'images, texte multi-colonnes et mises en page de texte complexes. UITextView est utilisé pour afficher des articles, descriptions, journaux, commentaires et tout texte multiligne dans iOS.
La différence entre UITextView et UITextField va bien au-delà du nombre de lignes. UITextField est un UIControl à ligne unique avec prise en charge de placeholder, vues gauche/droite et bouton d'effacement. UITextView est un UIScrollView multiligne avec un système TextKit complet pour le texte attribué. UITextField ne prend pas en charge NSAttributedString au niveau d'affichage (uniquement via attributedText avec limitations), UITextView gère NSAttributedString complètement avec différentes polices, styles de paragraphe et images intégrées. UITextField a un bouton d'effacement intégré (clearButtonMode), UITextView non — une implémentation personnalisée est nécessaire. UITextView se redimensionne automatiquement au contenu (intrinsicContentSize), UITextView nécessite une gestion manuelle de la hauteur via l'observation de contentSize ou des contraintes Auto Layout. UITextView prend en charge dataDetectorTypes (détection automatique des liens), UITextField le prend en charge depuis iOS 16+. Pour la saisie de texte multiligne (commentaires, notes, messages) choisissez UITextView. Pour les champs de formulaire (nom, email, mot de passe) utilisez UITextField.
| Fonctionnalité | UITextView | UITextField |
|---|---|---|
| Lignes | Multiligne | Ligne unique |
| Placeholder | Non (personnalisé) | Intégré |
| Attributs de texte | NSAttributedString complet | Limité |
| Data Detectors | Prise en charge complète | iOS 16+ |
| Images inline | Via NSTextAttachment | Non supporté |
| Défilement | Intégré (UIScrollView) | Non |
| Vue Gauche/Droite | Non | Intégrée |
NSAttributedString est une capacité fondamentale d'UITextView qui le distingue d'UITextField et UILabel. Une chaîne attribuée permet de définir différentes polices, couleurs, interlignes, alignements et liens au sein d'un même texte. Propriétés : textView.attributedText = attributedString. Attributs clés de NSAttributedString.Key : font (.systemFont, .boldSystemFont, UIFont personnalisé), foregroundColor, backgroundColor, paragraphStyle (NSMutableParagraphStyle avec lineSpacing, alignment, lineBreakMode), link (URL pour liens interactifs), underlineStyle, strikethroughStyle, shadow, baselineOffset, kern (espacement des lettres). Pour créer un attributedString utilisez init(string:, attributes:) ou NSMutableAttributedString pour ajouter des attributs à différentes plages. UITextView affiche automatiquement les liens (attribut link) comme interactifs — en appuyant dessus, la méthode déléguée shouldInteractWithURL est déclenchée. Pour réinitialiser les attributs pour une nouvelle saisie, utilisez 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 est un protocole qui gère l'édition et l'interaction avec le texte. Méthodes principales : textViewDidBeginEditing(textView) — appelée au début de l'édition ; textViewDidEndEditing — à la fin de l'édition ; textViewDidChange — à chaque modification de texte ; textViewDidChangeSelection — lors du changement de sélection ; textViewShouldInteractWithURL — lorsqu'un lien est touché (retourne Bool, autorise la transition) ; textViewShouldInteractWithTextAttachment — lorsqu'une image intégrée est touchée. Pour gérer les liens dans UITextView, remplacez shouldInteractWithURL — vous pouvez y : ouvrir l'URL dans SFSafariViewController, afficher UIAlertController pour confirmation, gérer des schémas d'URL personnalisés. Important : si textView.isEditable = true, les liens deviennent indisponibles pour un simple toucher — un double toucher est nécessaire. Pour les liens interactifs dans un textView éditable, utilisez des gesture recognizers.
SFSafariViewController est la méthode standard pour ouvrir des liens dans les applications iOS. Dans la méthode shouldInteractWithURL, créez SFSafariViewController avec l'URL et présentez-le modalement ou via navigationController. Pour les liens universels, utilisez UIApplication.shared.open(url, options) — mais cela sort de l'application. Pour empêcher l'ouverture des liens, retournez false dans shouldInteractWithURL et gérez l'URL vous-même.
NSTextContainer fait partie de l'architecture TextKit, définissant la zone géométrique où le texte d'UITextView est affiché. Chaque UITextView a un textContainer standard, configurable via : textView.textContainerInset — marges du texte par rapport aux bords du textView (UIEdgeInsets) ; textView.textContainer.lineFragmentPadding — remplissage horizontal à l'intérieur de chaque ligne ; textView.textContainer.maximumNumberOfLines — limite de lignes (0 = sans limite) ; textView.textContainer.exclusionPaths — tableau de UIBezierPath pour les zones que le texte doit contourner (images, formes personnalisées). Les ExclusionPaths permettent des mises en page complexes : le texte contourne une image de profil circulaire, une icône ou toute forme arbitraire. Pour la hauteur dynamique d'UITextView, observez contentSize via KVO ou délégué et mettez à jour les contraintes.
// 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 est une propriété d'UITextView qui reconnaît automatiquement et rend interactifs certains types de données dans le texte : .link (URL, email), .phoneNumber (numéros de téléphone), .address (adresses), .calendarEvent (dates et événements), .flightNumber (numéros de vol), .lookupSuggestion (suggestions de recherche), .trackingNumber (numéros de suivi), .money (montants), .shipmentTrackingNumber, .all (tous les types). Data Detector fonctionne avec NSDataDetector et URL, mettant automatiquement en évidence les données détectées. Pour personnaliser la gestion, définissez dataDetectorTypes et remplacez shouldInteractWithURL dans le délégué. Important : dataDetectorTypes ne fonctionne que pour URL et phoneNumber sans configuration supplémentaire — les autres types peuvent nécessiter iOS 16+. Data Detector n'entre pas en conflit avec l'attribut link dans NSAttributedString — les deux mécanismes fonctionnent en parallèle. Pour UITextView en lecture seule avec contenu (actualités, articles), définissez dataDetectorTypes = [.link, .phoneNumber].
Examinons deux exemples pratiques d'utilisation d'UITextView dans des applications iOS. Le premier — une vue texte en lecture seule avec texte attribué et détecteur de données pour afficher du contenu. Le second — une vue texte éditable avec placeholder paresseux et hauteur dynamique pour un formulaire de commentaire. Les deux exemples utilisent les meilleures pratiques d'UIKit : protocole délégué, Auto Layout et TextKit.
Le mode lecture seule est activé en définissant isEditable = false et isSelectable = true. Cela permet à l'utilisateur de sélectionner du texte et de toucher des liens, mais pas de modifier. Définissez dataDetectorTypes pour la détection automatique des liens, backgroundColor = .clear pour un fond transparent. Pour le contenu long, utilisez attributedText avec NSMutableParagraphStyle lineSpacing pour la lisibilité. Ajoutez des attributs link pour les liens clés dans le texte.
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
}
}
Le Placeholder pour UITextView n'est pas intégré — implémentez-le via un UILabel au-dessus du textView ou via attributedText avec vérification isEmpty. Une approche simple : un UILabel avec texte gris qui se cache au début de l'édition. Dans textViewDidChange, vérifiez la présence de texte et cachez/affichez le placeholder. Pour une solution plus élégante, utilisez la propriété typingAttributes pour définir la couleur du texte saisi. La hauteur dynamique du textView est obtenue en observant contentSize et en mettant à jour les contraintes — c'est un modèle standard pour les chats et formulaires de commentaires.
Questions Fréquentes
UITextView n'a pas de placeholder intégré. La solution standard : ajoutez un UILabel avec texte gris au-dessus du textView. Dans textViewDidBeginEditing, cachez l'étiquette, dans textViewDidEndEditing, montrez-la si le texte est vide. Alternativement : utilisez attributedText avec une couleur grise comme placeholder et réinitialisez-le au début de l'édition. Pour une solution prête à l'emploi, utilisez la bibliothèque KMPlaceholderTextView ou ReactorKit.
Définissez textContainerInset = .zero et lineFragmentPadding = 0 : textView.textContainerInset = UIEdgeInsets.zero ; textView.textContainer.lineFragmentPadding = 0. En complément : textView.contentInset = .zero. Cela supprimera complètement les marges des bords du textView jusqu'au texte. Notez que lineFragmentPadding par défaut est 5.
Vérifiez : isSelectable = true (nécessaire pour l'interaction), dataDetectorTypes inclut .link, le délégué ne retourne pas false dans shouldInteractWithURL. Si textView.isEditable = true, les liens ne sont pas disponibles pour un simple toucher — un double toucher est nécessaire. Pour les liens interactifs dans un textView éditable, ajoutez UITapGestureRecognizer au-dessus du textView et gérez les URL manuellement.
Définissez isScrollEnabled = true et ajoutez une contrainte de hauteur avec une valeur fixe. Le texte dépassant la hauteur défilera. Pour une UX optimale, utilisez maxHeight : observez contentSize et définissez la contrainte de hauteur ne dépassant pas maxHeight. Lorsque maxHeight est dépassé, activez scrollEnabled. C'est un modèle standard pour les champs de saisie de messages et commentaires.
Utilisez NSTextAttachment : créez un objet, définissez l'image et les bounds, puis créez un NSAttributedString à partir de la pièce jointe et insérez-le dans textView.attributedText. Exemple : let attachment = NSTextAttachment() ; attachment.image = image ; attachment.bounds = CGRect(x, y, width, height) ; let attributedString = NSAttributedString(attachment : attachment). L'image s'affichera inline dans le texte et défilera avec lui.
Résumé
Nous développerons une application mobile clé en main
IT Sectr crée des applications iOS et Android pour les startups et les entreprises depuis 2017. Nous vous conseillerons et vous proposerons la meilleure solution.
Lisez aussi