UITextView: co to jest, wprowadzanie wieloliniowe i zasada działania

Autor: IT Sectr Opublikowano: 2026-07-07 Czas czytania: 8 min

UITextView to wieloliniowy komponent tekstowy UIKit, dziedziczący po UIScrollView i obsługujący edycję tekstu atrybutowanego z osadzaniem linków i obrazów. Według dokumentacji Apple Developer (2025), UITextView udostępnia UITextViewDelegate z callbackami textViewDidChange, shouldInteractWithURL i shouldInteractWithTextAttachment do obsługi interakcji. W przeciwieństwie do UITextField, UITextView obsługuje przewijanie, style tekstowe przez typingAttributes i dataDetectorTypes do automatycznego wykrywania linków, adresów i dat. Jest to główny komponent do wyświetlania treści i wprowadzania tekstu wieloliniowego w aplikacjach iOS.

Najważniejsze

  • UITextView — wieloliniowe pole tekstowe UIKit, dziedziczące po UIScrollView z obsługą edycji
  • NSAttributedString — obsługa tekstu atrybutowanego: czcionki, kolory, odstępy międzywierszowe, linki
  • UITextViewDelegate — zarządzanie przez textViewDidChange, shouldInteractWithURL, didBeginEditing
  • Data Detector Types — automatyczne wykrywanie linków, adresów, dat, numerów telefonów w tekście
  • Text Container — system textContainer, exclusionPaths i lineFragmentPadding dla niestandardowego układu

Co to jest UITextView

UITextView to komponent UIKit przeznaczony do wyświetlania i edycji tekstu wieloliniowego. W przeciwieństwie do UILabel, UITextView obsługuje zaznaczanie tekstu, edycję, przewijanie przy przekroczeniu rozmiarów i tekst atrybutowany. Będąc dziedzicem UIScrollView, UITextView automatycznie włącza przewijanie pionowe i poziome przy przekroczeniu treści — konfigurowane przez isScrollEnabled. Klasa obsługuje edycję przez właściwość isEditable: ustaw false dla trybu tylko do odczytu. UITextView współpracuje z NSLayoutManager przez system TextKit: NSTextStorage (przechowywanie tekstu atrybutowanego) → NSLayoutManager (układ wierszy) → NSTextContainer (geometria obszaru tekstu). Ta architektura pozwala tworzyć niestandardowy układ z opływaniem obrazów, tekst wielokolumnowy i złożone układy tekstowe. UITextView jest używany do wyświetlania artykułów, opisów, logów, komentarzy i wszelkich tekstów wieloliniowych w iOS.

UITextView vs UITextField: kluczowe różnice

Różnica między UITextView a UITextField wykracza daleko poza liczbę wierszy. UITextField to jednowierszowy UIControl z obsługą placeholder, left/right view i przycisku czyszczenia. UITextView to wielowierszowy UIScrollView z pełnoprawnym systemem TextKit dla tekstu atrybutowanego. UITextField nie obsługuje NSAttributedString na poziomie wyświetlania (tylko przez attributedText z ograniczeniami), UITextView w pełni obsługuje NSAttributedString z różnymi czcionkami, stylami akapitów i osadzonymi obrazami. UITextField ma wbudowany przycisk czyszczenia (clearButtonMode), UITextView go nie ma — wymaga niestandardowej implementacji. UITextField automatycznie zmienia rozmiar do treści (intrinsicContentSize), UITextView wymaga ręcznego zarządzania wysokością przez obserwację contentSize lub ograniczenia Auto Layout. UITextView obsługuje dataDetectorTypes (automatyczne wykrywanie linków), UITextField obsługuje je od iOS 16+. Do wprowadzania tekstu wieloliniowego (komentarze, notatki, wiadomości) wybieraj UITextView. Do pól formularza (imię, email, hasło) używaj UITextField.

MożliwośćUITextViewUITextField
WierszeWieloliniowyJednowierszowy
PlaceholderNie (niestandardowy)Wbudowany
Atrybuty tekstuPełny NSAttributedStringOgraniczony
Data DetectorsPełna obsługaiOS 16+
Obrazy inlinePrzez NSTextAttachmentNieobsługiwane
PrzewijanieWbudowane (UIScrollView)Nie
Left/Right ViewNieWbudowane

NSAttributedString i formatowanie tekstu

NSAttributedString to fundamentalna możliwość UITextView, odróżniająca go od UITextField i UILabel. Atrybutowany ciąg pozwala ustawiać różne czcionki, kolory, odstępy międzywierszowe, wyrównanie i linki w ramach jednego tekstu. Właściwości: textView.attributedText = attributedString. Kluczowe atrybuty NSAttributedString.Key: font (.systemFont, .boldSystemFont, niestandardowy UIFont), foregroundColor, backgroundColor, paragraphStyle (NSMutableParagraphStyle z lineSpacing, alignment, lineBreakMode), link (URL dla interaktywnych linków), underlineStyle, strikethroughStyle, shadow, baselineOffset, kern (odstęp między znakami). Do tworzenia attributedString używaj init(string:, attributes:) lub NSMutableAttributedString do dodawania atrybutów do różnych zakresów. UITextView automatycznie wyświetla linki (link attribute) jako interaktywne — po naciśnięciu wywoływana jest metoda delegata shouldInteractWithURL. Do resetowania atrybutów dla nowego wprowadzania używaj typingAttributes.

swift
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

Delegat UITextViewDelegate i obsługa linków

UITextViewDelegate to protokół zarządzający edycją i interakcją z tekstem. Główne metody: textViewDidBeginEditing(textView) — wywoływana przy rozpoczęciu edycji; textViewDidEndEditing — przy zakończeniu; textViewDidChange — przy każdej zmianie tekstu; textViewDidChangeSelection — przy zmianie zaznaczenia; textViewShouldInteractWithURL — przy kliknięciu linku (zwraca Bool, czy przejście dozwolone); textViewShouldInteractWithTextAttachment — przy kliknięciu osadzonego obrazu. Do obsługi linków wewnątrz UITextView nadpisz shouldInteractWithURL — w nim możesz: otworzyć URL w SFSafariViewController, pokazać UIAlertController do potwierdzenia, obsłużyć niestandardowe schematy URL. Ważne: jeśli textView.isEditable = true, linki stają się niedostępne do kliknięcia do podwójnego tapnięcia — dla interaktywnych linków przy edycji używaj gesture recognizers.

Obsługa linków przez SFSafariViewController

SFSafariViewController to standardowy sposób otwierania linków w aplikacjach iOS. W metodzie shouldInteractWithURL utwórz SFSafariViewController z URL i przedstaw go modalnie lub przez navigationController. Dla uniwersalnych linków używaj UIApplication.shared.open(url, options) — ale to wychodzi poza aplikację. Aby zabronić otwierania linków, zwróć false w shouldInteractWithURL i obsłuż URL samodzielnie.

System Text Container: marginesy i exclusionPaths

NSTextContainer — część architektury TextKit, określająca geometryczny obszar, w którym wyświetlany jest tekst UITextView. Każdy UITextView ma standardowy textContainer, konfigurowany przez: textView.textContainerInset — marginesy tekstu od granic textView (UIEdgeInsets); textView.textContainer.lineFragmentPadding — poziomy margines wewnątrz każdego wiersza; textView.textContainer.maximumNumberOfLines — ograniczenie liczby wierszy (0 = bez limitu); textView.textContainer.exclusionPaths — tablica UIBezierPath dla obszarów, które tekst ma opływać (obrazy, niestandardowe kształty). ExclusionPaths pozwalają tworzyć złożony układ: tekst opływa okrągłe zdjęcie profilowe, ikonę lub dowolny kontur. Dla dynamicznego rozmiaru UITextView obserwuj contentSize przez KVO lub delegata i aktualizuj ograniczenia.

swift
// Dynamiczna wysokość UITextView przez 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 do opływania obrazów
let imageFrame = CGRect(x: 16, y: 100, width: 80, height: 80)
let exclusionPath = UIBezierPath(rect: imageFrame)
textView.textContainer.exclusionPaths = [exclusionPath]

Data Detector Types: automatyczne wykrywanie danych

dataDetectorTypes — właściwość UITextView, która automatycznie rozpoznaje i czyni interaktywnymi określone typy danych w tekście: .link (URL, email), .phoneNumber (numery telefonów), .address (adresy), .calendarEvent (daty i wydarzenia), .flightNumber (numery lotów), .lookupSuggestion (podpowiedzi wyszukiwania), .trackingNumber (numery śledzenia), .money (kwoty), .shipmentTrackingNumber, .all (wszystkie typy). Data Detector współpracuje z NSDataDetector i URL, automatycznie podświetlając wykryte dane. Do dostosowania obsługi ustaw dataDetectorTypes i nadpisz shouldInteractWithURL w delegacie. Ważne: dataDetectorTypes działa tylko dla URL i phoneNumber bez dodatkowej konfiguracji — pozostałe typy mogą wymagać iOS 16+. Data Detector nie koliduje z link attribute w NSAttributedString — oba mechanizmy działają równolegle. Dla UITextView tylko do odczytu z treścią (newsy, artykuły) ustaw dataDetectorTypes = [.link, .phoneNumber].

  • .link — URL, adresy email; wyświetlane jako niebieskie linki
  • .phoneNumber — numery telefonów; kliknięcie pokazuje akcję Call
  • .address — adresy pocztowe; kliknięcie otwiera Maps
  • .calendarEvent — daty i godziny; kliknięcie tworzy wydarzenie w kalendarzu
  • .flightNumber — numery lotów (iOS 16+); szybkie sprawdzenie lotu

Przykłady kodu z UITextView

Rozważmy dwa praktyczne przykłady użycia UITextView w aplikacjach iOS. Pierwszy — text view tylko do odczytu z tekstem atrybutowanym i data detector do wyświetlania treści. Drugi — edytowalny text view z leniwym placeholderem i dynamiczną wysokością do formularza komentarza. Oba przykłady wykorzystują best practices UIKit: protokół delegata, Auto Layout i TextKit.

UITextView tylko do odczytu z treścią i linkami

Tryb tylko do odczytu włącza się przez ustawienie isEditable = false i isSelectable = true. Pozwala to użytkownikowi zaznaczać tekst i klikać linki, ale nie edytować. Ustaw dataDetectorTypes do automatycznego wykrywania linków, backgroundColor = .clear dla przezroczystego tła. Do wyświetlania długiej treści używaj attributedText z NSMutableParagraphStyle lineSpacing dla czytelności. Dodaj link attributes dla kluczowych linków w tekście.

swift
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 }
        // Załaduj treść z URL i ustaw attributedText
    }
}

Edytowalny UITextView z placeholderem

Placeholder dla UITextView nie jest wbudowany — zaimplementuj go przez UILabel nad textView lub przez attributedText ze sprawdzeniem isEmpty. Proste podejście: UILabel z szarym tekstem, który ukrywa się przy rozpoczęciu edycji. W textViewDidChange sprawdzaj obecność tekstu i ukrywaj/pokazuj placeholder. Dla bardziej eleganckiego rozwiązania używaj właściwości typingAttributes do ustawienia koloru wprowadzanego tekstu. Dynamiczna wysokość textView osiągana jest przez obserwację contentSize i aktualizację ograniczeń — to standardowy wzorzec dla czatów i formularzy komentarzy.

Często zadawane pytania

Jak dodać placeholder w UITextView?

UITextView nie ma wbudowanego placeholdera. Standardowe rozwiązanie: dodaj UILabel z szarym tekstem nad textView. W textViewDidBeginEditing ukrywaj label, w textViewDidEndEditing pokazuj, jeśli tekst jest pusty. Alternatywnie: używaj attributedText z szarym kolorem jako placeholdera i resetuj przy rozpoczęciu edycji. Dla gotowego rozwiązania użyj biblioteki KMPlaceholderTextView lub ReactorKit.

Jak usunąć marginesy w UITextView?

Ustaw textContainerInset = .zero i lineFragmentPadding = 0: textView.textContainerInset = UIEdgeInsets.zero; textView.textContainer.lineFragmentPadding = 0. Dodatkowo: textView.contentInset = .zero. To całkowicie usunie marginesy od krawędzi textView do tekstu. Pamiętaj, że lineFragmentPadding domyślnie wynosi 5.

Dlaczego UITextView nie otwiera linków?

Sprawdź: isSelectable = true (niezbędne do interakcji), dataDetectorTypes zawiera .link, delegat nie zwraca false w shouldInteractWithURL. Jeśli textView.isEditable = true, linki są niedostępne do pojedynczego kliknięcia — wymagane jest podwójne tapnięcie. Dla interaktywnych linków w edytowalnym textView dodaj UITapGestureRecognizer nad textView i obsługuj URL ręcznie.

Jak zrobić UITextView o stałej wysokości z przewijaniem?

Ustaw isScrollEnabled = true i dodaj height constraint ze stałą wartością. Tekst przekraczający wysokość będzie przewijany. Dla optymalnego UX używaj maxHeight: obserwuj contentSize i ustawiaj height constraint nie wyższy niż maxHeight. Po przekroczeniu maxHeight włącz scrollEnabled. To standardowy wzorzec dla pól wprowadzania wiadomości i komentarzy.

Jak wstawić obraz w UITextView?

Użyj NSTextAttachment: utwórz obiekt, ustaw image i bounds, następnie utwórz NSAttributedString z attachment i wstaw do textView.attributedText. Przykład: let attachment = NSTextAttachment(); attachment.image = image; attachment.bounds = CGRect(x, y, width, height); let attributedString = NSAttributedString(attachment: attachment). Obraz wyświetli się inline w tekście i będzie przewijany razem z nim.

Podsumowanie

  • UITextView — wieloliniowy komponent tekstowy UIKit, dziedziczący po UIScrollView z obsługą TextKit
  • NSAttributedString — kluczowa możliwość do formatowania czcionek, kolorów, linków i akapitów
  • UITextViewDelegate — zarządzanie edycją i obsługa kliknięć linków i załączników
  • Data Detector Types — automatyczne wykrywanie URL, telefonów, adresów i dat przez NSDataDetector
  • Text Container — system z exclusionPaths, lineFragmentPadding i textContainerInset do układu
  • Placeholder — nie wbudowany, implementowany przez UILabel lub attributedText z szarym kolorem
  • Dynamic height — obserwacja contentSize i aktualizacja ograniczeń dla automatycznej wysokości
  • UITextView różni się od UITextField obsługą wieloliniowości, atrybutów, przewijania i data detectors

Opracujemy aplikację mobilną pod klucz

IT Sectr tworzy aplikacje na iOS i Androida dla startupów i firm od 2017 roku. Doradzimy Ci i zaproponujemy najlepsze rozwiązanie.

Omów projekt

Przeczytaj również