UITextView یک مؤلفه متنی چندخطی UIKit است که از UIScrollView ارث بری میکند و از ویرایش متن ویژگیدار با جاسازی لینکها و تصاویر پشتیبانی میکند. طبق مستندات Apple Developer (2025)، UITextView UITextViewDelegate را با callbackهای 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، نمای چپ/راست و دکمه پاک کردن است. UITextView یک UIScrollView چندخطی با سیستم کامل TextKit برای متن ویژگیدار است. UITextField از NSAttributedString در سطح نمایش پشتیبانی نمیکند (فقط از طریق attributedText با محدودیتها)، UITextView NSAttributedString را با فونتهای مختلف، سبکهای پاراگراف و تصاویر جاسازی شده به طور کامل پردازش میکند. UITextField دارای دکمه پاک کردن داخلی (clearButtonMode) است، UITextView آن را ندارد — نیاز به پیادهسازی سفارشی دارد. UITextField به طور خودکار اندازه خود را با محتوا تنظیم میکند (intrinsicContentSize)، UITextView نیاز به مدیریت دستی ارتفاع از طریق مشاهده contentSize یا محدودیتهای Auto Layout دارد. UITextView از dataDetectorTypes (تشخیص خودکار لینکها) پشتیبانی میکند، UITextField آن را از iOS 16+ پشتیبانی میکند. برای ورود متن چندخطی (نظرات، یادداشتها، پیامها) UITextView را انتخاب کنید. برای فیلدهای فرم (نام، ایمیل، رمز عبور) از UITextField استفاده کنید.
| قابلیت | UITextView | UITextField |
|---|---|---|
| خطوط | چندخطی | تکخطی |
| Placeholder | ندارد (سفارشی) | داخلی |
| ویژگیهای متن | NSAttributedString کامل | محدود |
| Data Detectors | پشتیبانی کامل | iOS 16+ |
| تصاویر درون خطی | از طریق NSTextAttachment | پشتیبانی نمیشود |
| اسکرول | داخلی (UIScrollView) | ندارد |
| نمای چپ/راست | ندارد | داخلی |
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) استفاده کنید — اما این از برنامه خارج میشود. برای ممانعت از باز شدن لینکها در shouldInteractWithURL false برگردانید و 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، ایمیل)، .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 قابل ویرایش با placeholder تنبل و ارتفاع پویا برای فرم نظر. هر دو مثال از best practices 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 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 است، دلیگیت در shouldInteractWithURL false برنمیگرداند. اگر textView.isEditable = true باشد، لینکها برای کلیک تکی در دسترس نیستند — نیاز به ضربه دوگانه دارند. برای لینکهای تعاملی در textView قابل ویرایش یک UITapGestureRecognizer روی textView اضافه کنید و URL را دستی پردازش کنید.
isScrollEnabled = true تنظیم کنید و یک height constraint با مقدار ثابت اضافه کنید. متن بیشتر از ارتفاع اسکرول خواهد شد. برای UX بهینه از maxHeight استفاده کنید: contentSize را مشاهده کنید و height constraint را بیشتر از maxHeight تنظیم نکنید. هنگام تجاوز از maxHeight scrollEnabled را فعال کنید. این الگوی استاندارد برای فیلدهای ورود پیام و نظر است.
از NSTextAttachment استفاده کنید: یک شی ایجاد کنید، image و bounds را تنظیم کنید، سپس از attachment یک NSAttributedString ایجاد کرده و در textView.attributedText وارد کنید. مثال: let attachment = NSTextAttachment(); attachment.image = image; attachment.bounds = CGRect(x, y, width, height); let attributedString = NSAttributedString(attachment: attachment). تصویر به صورت درون خطی در متن نمایش داده میشود و همراه با آن اسکرول میکند.
خلاصه
ما یک اپلیکیشن موبایل به صورت کلید در دست توسعه خواهیم داد
IT Sectr از سال 2017 برنامههای iOS و Android را برای استارتاپها و کسبوکارها ایجاد میکند. ما به شما مشاوره میدهیم و بهترین راهحل را پیشنهاد خواهیم کرد.
همچنین بخوانید