UITextView: چیست، ورودی چندخطی و اصل کار

نویسنده: IT Sectr منتشر شده: 2026-07-07 زمان مطالعه: 8 دقیقه

UITextView یک مؤلفه متنی چندخطی UIKit است که از UIScrollView ارث بری می‌کند و از ویرایش متن ویژگی‌دار با جاسازی لینک‌ها و تصاویر پشتیبانی می‌کند. طبق مستندات Apple Developer (2025)، UITextView UITextViewDelegate را با callbackهای textViewDidChange، shouldInteractWithURL و shouldInteractWithTextAttachment برای مدیریت تعاملات فراهم می‌کند. برخلاف UITextField، UITextView از اسکرول، سبک‌های متنی از طریق typingAttributes و dataDetectorTypes برای تشخیص خودکار لینک‌ها، آدرس‌ها و تاریخ‌ها پشتیبانی می‌کند. این مؤلفه اصلی برای نمایش محتوا و ورود متن چندخطی در برنامه‌های iOS است.

نکات اصلی

  • UITextView — فیلد متنی چندخطی UIKit، وارث UIScrollView با پشتیبانی از ویرایش
  • NSAttributedString — پشتیبانی از متن ویژگی‌دار: فونت‌ها، رنگ‌ها، فاصله خطوط، لینک‌ها
  • UITextViewDelegate — مدیریت از طریق textViewDidChange، shouldInteractWithURL، didBeginEditing
  • Data Detector Types — تشخیص خودکار لینک‌ها، آدرس‌ها، تاریخ‌ها، شماره تلفن‌ها در متن
  • Text Container — سیستم textContainer، exclusionPaths و lineFragmentPadding برای چیدمان سفارشی

UITextView چیست

UITextView یک مؤلفه UIKit است که برای نمایش و ویرایش متن چندخطی طراحی شده است. برخلاف UILabel، UITextView از انتخاب متن، ویرایش، اسکرول در هنگام تجاوز از اندازه و متن ویژگی‌دار پشتیبانی می‌کند. به عنوان وارث UIScrollView، UITextView به طور خودکار اسکرول عمودی و افقی را در هنگام بیشتر شدن محتوا فعال می‌کند — این از طریق isScrollEnabled قابل تنظیم است. کلاس از ویرایش از طریق ویژگی isEditable پشتیبانی می‌کند: برای حالت فقط خواندنی false تنظیم کنید. UITextView با NSLayoutManager از طریق سیستم TextKit کار می‌کند: NSTextStorage (ذخیره متن ویژگی‌دار) → NSLayoutManager (چیدمان خطوط) → NSTextContainer (هندسه ناحیه متن). این معماری امکان ایجاد چیدمان سفارشی با چرخش متن به دور تصاویر، متن چندستونه و طرح‌بندی‌های پیچیده متنی را فراهم می‌کند. UITextView برای نمایش مقالات، توضیحات، لاگ‌ها، نظرات و هر متن چندخطی در iOS استفاده می‌شود.

UITextView در مقابل UITextField: تفاوت‌های کلیدی

تفاوت بین 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 استفاده کنید.

قابلیتUITextViewUITextField
خطوطچندخطیتک‌خطی
Placeholderندارد (سفارشی)داخلی
ویژگی‌های متنNSAttributedString کاملمحدود
Data Detectorsپشتیبانی کاملiOS 16+
تصاویر درون خطیاز طریق NSTextAttachmentپشتیبانی نمی‌شود
اسکرولداخلی (UIScrollView)ندارد
نمای چپ/راستنداردداخلی

NSAttributedString و قالب‌بندی متن

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(stringattributes:) یا NSMutableAttributedString برای افزودن ویژگی‌ها به محدوده‌های مختلف استفاده کنید. UITextView به طور خودکار لینک‌ها (link attribute) را به صورت تعاملی نمایش می‌دهد — با فشار دادن، متد دلیگیت shouldInteractWithURL فراخوانی می‌شود. برای بازنشانی ویژگی‌ها برای ورود جدید از 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

دلیگیت UITextViewDelegate و پردازش لینک‌ها

UITextViewDelegate یک پروتکل است که ویرایش و تعامل با متن را مدیریت می‌کند. متدهای اصلی: textViewDidBeginEditing(textView) — در شروع ویرایش فراخوانی می‌شود؛ textViewDidEndEditing — در پایان؛ textViewDidChange — در هر تغییر متن؛ textViewDidChangeSelection — در تغییر انتخاب؛ textViewShouldInteractWithURL — هنگام کلیک روی لینک (Bool برمی‌گرداند، آیا انتقال مجاز است)؛ textViewShouldInteractWithTextAttachment — هنگام کلیک روی تصویر جاسازی شده. برای پردازش لینک‌های داخل UITextView shouldInteractWithURL را بازنویسی کنید — در آن می‌توانید: URL را در SFSafariViewController باز کنید، UIAlertController برای تأیید نمایش دهید، طرح‌های URL سفارشی را پردازش کنید. مهم: اگر textView.isEditable = true باشد، لینک‌ها تا ضربه دوگانه برای کلیک در دسترس نیستند — برای لینک‌های تعاملی در هنگام ویرایش از gesture recognizers استفاده کنید.

پردازش لینک‌ها از طریق SFSafariViewController

SFSafariViewController روش استاندارد باز کردن لینک‌ها در برنامه‌های iOS است. در متد shouldInteractWithURL یک SFSafariViewController با URL ایجاد کنید و آن را به صورت modal یا از طریق navigationController نمایش دهید. برای لینک‌های جهانی از UIApplication.shared.open(url, options) استفاده کنید — اما این از برنامه خارج می‌شود. برای ممانعت از باز شدن لینک‌ها در shouldInteractWithURL false برگردانید و URL را خودتان پردازش کنید.

سیستم Text Container: حاشیه‌ها و exclusionPaths

NSTextContainer — بخشی از معماری TextKit که ناحیه هندسی نمایش متن UITextView را تعیین می‌کند. هر UITextView یک textContainer استاندارد دارد که از طریق: textView.textContainerInset — حاشیه‌های متن از مرزهای textView (UIEdgeInsets)؛ textView.textContainer.lineFragmentPadding — حاشیه افقی داخل هر خط؛ textView.textContainer.maximumNumberOfLines — محدودیت تعداد خطوط (0 = بدون محدودیت)؛ textView.textContainer.exclusionPaths — آرایه‌ای از UIBezierPath برای مناطقی که متن باید دور آن‌ها بچرخد (تصاویر، اشکال سفارشی) قابل تنظیم است. ExclusionPaths امکان ایجاد چیدمان پیچیده را فراهم می‌کند: متن دور عکس پروفایل دایره‌ای، آیکون یا هر خط دلخواه می‌چرخد. برای اندازه پویای UITextView contentSize را از طریق KVO یا دلیگیت مشاهده کنید و محدودیت‌ها را به‌روز کنید.

swift
// ارتفاع پویای 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]

Data Detector Types: تشخیص خودکار داده

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] را تنظیم کنید.

  • .link — URL، آدرس‌های ایمیل؛ به صورت لینک‌های آبی نمایش داده می‌شوند
  • .phoneNumber — شماره تلفن‌ها؛ کلیک عمل Call را نشان می‌دهد
  • .address — آدرس‌های پستی؛ کلیک Maps را باز می‌کند
  • .calendarEvent — تاریخ‌ها و زمان‌ها؛ کلیک یک رویداد تقویم ایجاد می‌کند
  • .flightNumber — شماره پروازها (iOS 16+)؛ بررسی سریع پرواز

نمونه کد با UITextView

بیایید دو مثال عملی استفاده از UITextView در برنامه‌های iOS را بررسی کنیم. اولی — text view فقط خواندنی با متن ویژگی‌دار و data detector برای نمایش محتوا. دومی — text view قابل ویرایش با placeholder تنبل و ارتفاع پویا برای فرم نظر. هر دو مثال از best practices UIKit استفاده می‌کنند: پروتکل دلیگیت، Auto Layout و TextKit.

UITextView فقط خواندنی با محتوا و لینک‌ها

حالت فقط خواندنی با تنظیم isEditable = false و isSelectable = true فعال می‌شود. این به کاربر امکان می‌دهد متن را انتخاب کرده و روی لینک‌ها کلیک کند، اما ویرایش نکند. برای تشخیص خودکار لینک‌ها dataDetectorTypes، برای پس‌زمینه شفاف backgroundColor = .clear تنظیم کنید. برای نمایش محتوای طولانی از attributedText با NSMutableParagraphStyle lineSpacing برای خوانایی استفاده کنید. برای لینک‌های کلیدی در متن link attributes اضافه کنید.

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 }
        // بارگیری محتوا از URL و تنظیم attributedText
    }
}

UITextView قابل ویرایش با placeholder

Placeholder برای UITextView داخلی نیست — آن را از طریق UILabel روی textView یا از طریق attributedText با بررسی isEmpty پیاده‌سازی کنید. رویکرد ساده: UILabel با متن خاکستری که در شروع ویرایش مخفی می‌شود. در textViewDidChange وجود متن را بررسی کنید و placeholder را مخفی/نمایش دهید. برای راه‌حل ظریف‌تر از ویژگی typingAttributes برای تنظیم رنگ متن ورودی استفاده کنید. ارتفاع پویای textView از طریق مشاهده contentSize و به‌روزرسانی محدودیت‌ها به دست می‌آید — این الگوی استاندارد برای چت‌ها و فرم‌های نظر است.

سوالات متداول

چگونه در UITextView placeholder اضافه کنیم؟

UITextView placeholder داخلی ندارد. راه‌حل استاندارد: یک UILabel با متن خاکستری روی textView اضافه کنید. در textViewDidBeginEditing label را مخفی کنید، در textViewDidEndEditing اگر متن خالی است نمایش دهید. جایگزین: از attributedText با رنگ خاکستری به عنوان placeholder استفاده کنید و در شروع ویرایش بازنشانی کنید. برای راه‌حل آماده از کتابخانه KMPlaceholderTextView یا ReactorKit استفاده کنید.

چگونه حاشیه‌ها را در UITextView حذف کنیم؟

textContainerInset = .zero و lineFragmentPadding = 0 تنظیم کنید: textView.textContainerInset = UIEdgeInsets.zero; textView.textContainer.lineFragmentPadding = 0. اضافی: textView.contentInset = .zero. این کاملاً حاشیه‌ها را از لبه‌های textView تا متن حذف می‌کند. توجه داشته باشید که lineFragmentPadding پیش‌فرض 5 است.

چرا UITextView لینک‌ها را باز نمی‌کند؟

بررسی کنید: isSelectable = true (برای تعامل ضروری است)، dataDetectorTypes شامل .link است، دلیگیت در shouldInteractWithURL false برنمی‌گرداند. اگر textView.isEditable = true باشد، لینک‌ها برای کلیک تکی در دسترس نیستند — نیاز به ضربه دوگانه دارند. برای لینک‌های تعاملی در textView قابل ویرایش یک UITapGestureRecognizer روی textView اضافه کنید و URL را دستی پردازش کنید.

چگونه UITextView با ارتفاع ثابت و اسکرول بسازیم؟

isScrollEnabled = true تنظیم کنید و یک height constraint با مقدار ثابت اضافه کنید. متن بیشتر از ارتفاع اسکرول خواهد شد. برای UX بهینه از maxHeight استفاده کنید: contentSize را مشاهده کنید و height constraint را بیشتر از maxHeight تنظیم نکنید. هنگام تجاوز از maxHeight scrollEnabled را فعال کنید. این الگوی استاندارد برای فیلدهای ورود پیام و نظر است.

چگونه تصویر در UITextView وارد کنیم؟

از 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). تصویر به صورت درون خطی در متن نمایش داده می‌شود و همراه با آن اسکرول می‌کند.

خلاصه

  • UITextView — مؤلفه متنی چندخطی UIKit، وارث UIScrollView با پشتیبانی TextKit
  • NSAttributedString — قابلیت کلیدی برای قالب‌بندی فونت‌ها، رنگ‌ها، لینک‌ها و پاراگراف‌ها
  • UITextViewDelegate — مدیریت ویرایش و پردازش کلیک روی لینک‌ها و پیوست‌ها
  • Data Detector Types — تشخیص خودکار URL، تلفن، آدرس و تاریخ از طریق NSDataDetector
  • Text Container — سیستم با exclusionPaths، lineFragmentPadding و textContainerInset برای چیدمان
  • Placeholder — داخلی نیست، از طریق UILabel یا attributedText با رنگ خاکستری پیاده‌سازی می‌شود
  • Dynamic height — مشاهده contentSize و به‌روزرسانی محدودیت‌ها برای ارتفاع خودکار
  • UITextView با پشتیبانی از چندخطی، ویژگی‌ها، اسکرول و data detectors از UITextField متمایز می‌شود

ما یک اپلیکیشن موبایل به صورت کلید در دست توسعه خواهیم داد

IT Sectr از سال 2017 برنامه‌های iOS و Android را برای استارتاپ‌ها و کسب‌وکارها ایجاد می‌کند. ما به شما مشاوره می‌دهیم و بهترین راه‌حل را پیشنهاد خواهیم کرد.

بحث درباره پروژه

همچنین بخوانید