Το UITextView είναι ένα πολυγραμμικό στοιχείο κειμένου UIKit, που κληρονομεί το UIScrollView και υποστηρίζει επεξεργασία χαρακτηρισμένου κειμένου με ενσωμάτωση συνδέσεων και εικόνων. Σύμφωνα με την τεκμηρίωση της Apple Developer (2025), το UITextView παρέχει UITextViewDelegate με callbacks textViewDidChange, shouldInteractWithURL και shouldInteractWithTextAttachment για το χειρισμό αλληλεπιδράσεων. Σε αντίθεση με το UITextField, το UITextView υποστηρίζει κύλιση, στυλ κειμένου μέσω typingAttributes και dataDetectorTypes για αυτόματη ανίχνευση συνδέσμων, διευθύνσεων και ημερομηνιών. Αυτό είναι το κύριο στοιχείο για εμφάνιση περιεχομένου και εισαγωγή πολυγραμμικού κειμένου σε εφαρμογές iOS.
Κύρια σημεία
UITextView είναι ένα στοιχείο UIKit που προορίζεται για εμφάνιση και επεξεργασία πολυγραμμικού κειμένου. Σε αντίθεση με το UILabel, το UITextView υποστηρίζει επιλογή κειμένου, επεξεργασία, κύλιση κατά υπέρβαση διαστάσεων και χαρακτηρισμένο κείμενο. Ως κληρονόμος του UIScrollView, το UITextView ενεργοποιεί αυτόματα κάθετη και οριζόντια κύλιση κατά υπέρβαση περιεχομένου — αυτό ρυθμίζεται μέσω isScrollEnabled. Η κλάση υποστηρίζει επεξεργασία μέσω της ιδιότητας isEditable: ορίστε false για λειτουργία μόνο για ανάγνωση. Το UITextView λειτουργεί με NSLayoutManager μέσω του συστήματος TextKit: NSTextStorage (αποθήκευση χαρακτηρισμένου κειμένου) → NSLayoutManager (διάταξη γραμμών) → NSTextContainer (γεωμετρία περιοχής κειμένου). Αυτή η αρχιτεκτονική επιτρέπει τη δημιουργία προσαρμοσμένης διάταξης με ροή κειμένου γύρω από εικόνες, πολυστηλικό κείμενο και σύνθετες διατάξεις κειμένου. Το UITextView χρησιμοποιείται για εμφάνιση άρθρων, περιγραφών, αρχείων καταγραφής, σχολίων και οποιουδήποτε πολυγραμμικού κειμένου στο iOS.
Η διαφορά μεταξύ UITextView και UITextField υπερβαίνει κατά πολύ τον αριθμό γραμμών. Το UITextField είναι ένα μονογραμμικό UIControl με υποστήριξη placeholder, left/right view και κουμπιού διαγραφής. Το UITextView είναι ένα πολυγραμμικό UIScrollView με πλήρες σύστημα TextKit για χαρακτηρισμένο κείμενο. Το UITextField δεν υποστηρίζει NSAttributedString σε επίπεδο εμφάνισης (μόνο μέσω attributedText με περιορισμούς), το UITextView επεξεργάζεται πλήρως το NSAttributedString με διαφορετικές γραμματοσειρές, στυλ παραγράφων και ενσωματωμένες εικόνες. Το UITextField έχει ενσωματωμένο κουμπί διαγραφής (clearButtonMode), το UITextView δεν έχει — απαιτεί προσαρμοσμένη υλοποίηση. Το UITextView αλλάζει αυτόματα μέγεθος ανάλογα με το περιεχόμενο (intrinsicContentSize), το UITextView απαιτεί χειροκίνητη διαχείριση ύψους μέσω παρακολούθησης contentSize ή περιορισμών Auto Layout. Το 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. Σημαντικό: εάν textView.isEditable = true, οι σύνδεσμοι δεν είναι διαθέσιμοι για πάτημα μέχρι διπλό πάτημα — για διαδραστικούς συνδέσμους κατά την επεξεργασία χρησιμοποιήστε gesture recognizers.
SFSafariViewController είναι ο τυπικός τρόπος ανοίγματος συνδέσμων σε εφαρμογές iOS. Στη μέθοδο shouldInteractWithURL δημιουργήστε ένα SFSafariViewController με το URL και παρουσιάστε το modal ή μέσω 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 για περιοχές που το κείμενο πρέπει να αποφεύγει (εικόνες, προσαρμοσμένα σχήματα). Τα exclusionPaths επιτρέπουν τη δημιουργία σύνθετης διάταξης: το κείμενο ρέει γύρω από μια στρογγυλή φωτογραφία προφίλ, εικονίδιο ή οποιοδήποτε αυθαίρετο περίγραμμα. Για δυναμικό μέγεθος UITextView παρακολουθήστε το contentSize μέσω KVO ή αντιπροσώπου και ενημερώστε τους περιορισμούς.
// Δυναμικό ύψος UITextView μέσω 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 για περιτύλιξη εικόνας
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 — και οι δύο μηχανισμοί λειτουργούν παράλληλα. Για UITextView μόνο για ανάγνωση με περιεχόμενο (ειδήσεις, άρθρα) ορίστε dataDetectorTypes = [.link, .phoneNumber].
Ας εξετάσουμε δύο πρακτικά παραδείγματα χρήσης του UITextView σε εφαρμογές iOS. Το πρώτο — text view μόνο για ανάγνωση με χαρακτηρισμένο κείμενο και data detector για εμφάνιση περιεχομένου. Το δεύτερο — επεξεργάσιμο text view με lazy placeholder και δυναμικό ύψος για φόρμα σχολίου. Και τα δύο παραδείγματα χρησιμοποιούν βέλτιστες πρακτικές UIKit: πρωτόκολλο αντιπροσώπου, Auto Layout και TextKit.
Λειτουργία μόνο για ανάγνωση ενεργοποιείται με ορισμό 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 }
// Φόρτωση περιεχομένου από URL και ορισμός attributedText
}
}
Placeholder για UITextView δεν είναι ενσωματωμένος — υλοποιήστε τον μέσω UILabel πάνω από το textView ή μέσω attributedText με έλεγχο isEmpty. Απλή προσέγγιση: ένα UILabel με γκρι κείμενο που κρύβεται κατά την έναρξη επεξεργασίας. Στο textViewDidChange ελέγξτε την παρουσία κειμένου και κρύψτε/εμφανίστε το placeholder. Για πιο κομψή λύση χρησιμοποιήστε την ιδιότητα typingAttributes για ορισμό χρώματος εισαγόμενου κειμένου. Το δυναμικό ύψος του textView επιτυγχάνεται μέσω παρακολούθησης contentSize και ενημέρωσης περιορισμών — αυτό είναι το τυπικό μοτίβο για συνομιλίες και φόρμες σχολίων.
Συχνές Ερωτήσεις
UITextView δεν έχει ενσωματωμένο placeholder. Τυπική λύση: προσθέστε ένα UILabel με γκρι κείμενο πάνω από το textView. Στο textViewDidBeginEditing κρύψτε την ετικέτα, στο 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 με σταθερή τιμή. Το κείμενο που υπερβαίνει το ύψος θα κυλά. Για βέλτιστη εμπειρία χρήστη χρησιμοποιήστε 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. Θα σας συμβουλεύσουμε και θα προτείνουμε την καλύτερη λύση.
Διαβάστε επίσης