UITableView — iOS में वर्टिकल सूचियाँ प्रदर्शित करने के लिए UIKit का मुख्य घटक। टेबल की प्रत्येक पंक्ति एक UITableViewCell है जिसमें पूर्वनिर्धारित शैलियाँ होती हैं। हम UITableView की मूल बातें समझाते हैं: DataSource, डेलिगेट, सेल पुन: उपयोग और iOS ऐप्स में टेबल का प्रदर्शन। Apple (Human Interface Guidelines, 2026) के अनुसार, UITableView iOS में सबसे अधिक उपयोग किया जाने वाला UI घटक बना हुआ है — App Store के शीर्ष 100 में 85% ऐप्स में कम से कम एक टेबल होती है। जटिल लेआउट के लिए, UICollectionView के बारे में लेख पढ़ें।
मुख्य बिंदु
UITableView UIKit फ्रेमवर्क का एक वर्ग है जो एक कॉलम में पंक्तियों की स्क्रॉल करने योग्य सूची प्रदर्शित करने के लिए डिज़ाइन किया गया है। प्रत्येक पंक्ति एक UITableViewCell ऑब्जेक्ट द्वारा दर्शाई जाती है। UITableView पहली बार iPhone OS 2 (2008) में दिखाई दिया और तब से iOS में सूचियों के लिए मुख्य घटक बना हुआ है। UITableView की आर्किटेक्चर MVC पैटर्न पर आधारित है: डेटा DataSource द्वारा प्रबंधित किया जाता है, दिखावट और व्यवहार Delegate द्वारा, और प्रस्तुति स्वयं टेबल द्वारा।
दो टेबल शैलियाँ: .plain (वैकल्पिक अनुभागों के साथ सतत सूची) और .grouped (गोल कोनों और मार्जिन के साथ समूहित अनुभाग)। iOS 13 ने .insetGrouped जोड़ा — किनारों से मार्जिन वाली grouped शैली, जो सेटिंग्स और हेल्थ ऐप्स में उपयोग होती है। शैली का चुनाव डिफ़ॉल्ट दिखावट को प्रभावित करता है: plain टेबल्स स्क्रॉल करते समय अनुभाग हेडर को ऊपर जोड़ती हैं (स्टिकी हेडर), grouped टेबल्स नहीं।
iOS 8 से शुरू करते हुए, UITableView सेल्फ-साइज़िंग सेल्स का समर्थन करता है। सक्षम करने के लिए, tableView.estimatedRowHeight (जैसे, 80) और tableView.rowHeight = UITableView.automaticDimension सेट करें। टेबल सेल के अंदर Auto Layout कंस्ट्रेंट के आधार पर स्वचालित रूप से पंक्ति की ऊँचाई की गणना करती है। जटिल सेल्स के लिए सेल्फ-साइज़िंग प्रदर्शन कम करता है — 500+ आइटम वाली टेबल्स के लिए फिक्स्ड ऊँचाई (rowHeight) का उपयोग करें।
UITableViewCell चार अंतर्निर्मित शैलियाँ प्रदान करता है जो कस्टम सेल बनाने की आवश्यकता के बिना 80% परिदृश्यों को कवर करती हैं। प्रत्येक शैली textLabel, detailTextLabel और imageView के संयोजन से बनी होती है। शैली को init(style:reuseIdentifier:) के माध्यम से सेल को इनिशियलाइज़ करते समय चुना जाता है।
| शैली | textLabel | detailTextLabel | imageView | उदाहरण |
|---|---|---|---|---|
| .default (.basic) | बाएँ, बोल्ड | कोई नहीं | वैकल्पिक | मेनू, आइटम की सूची |
| .subtitle | बाएँ, बोल्ड | textLabel के नीचे, ग्रे | वैकल्पिक | संपर्क, प्लेलिस्ट |
| .value1 | बाएँ, बोल्ड | दाएँ, ग्रे | कोई नहीं | मानों के साथ सेटिंग्स |
| .value2 | दाएँ, नीला | बाएँ, ग्रे | कोई नहीं | फ़ोन बुक (iOS 6-शैली) |
// कस्टम सेल के साथ टेबल बनाना
class ContactListController: UIViewController {
private let tableView = UITableView(frame: .zero, style: .insetGrouped)
override func viewDidLoad() {
super.viewDidLoad()
tableView.register(UITableViewCell.self, forCellReuseIdentifier: "cell")
tableView.dataSource = self
tableView.delegate = self
tableView.rowHeight = 60
view.addSubview(tableView)
// Auto Layout
tableView.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
tableView.topAnchor.constraint(equalTo: view.topAnchor),
tableView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
tableView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
tableView.bottomAnchor.constraint(equalTo: view.bottomAnchor)
])
}
}
extension ContactListController: UITableViewDataSource {
func tableView(_ tableView: UITableView,
numberOfRowsInSection section: Int) -> Int {
contacts.count
}
func tableView(_ tableView: UITableView,
cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
let contact = contacts[indexPath.row]
var content = cell.defaultContentConfiguration()
content.text = contact.name
content.secondaryText = contact.phone
content.image = UIImage(systemName: "person.circle")
cell.contentConfiguration = content
return cell
}
}
UIContentConfiguration (iOS 14+) — textLabel/detailTextLabel तक सीधी पहुँच के बजाय contentConfiguration के माध्यम से सेल कॉन्फ़िगर करने का आधुनिक तरीका। cell.defaultContentConfiguration() का उपयोग करें या कस्टम UIContentConfiguration बनाएँ। लाभ: डायनामिक टाइप, डार्क मोड और VoiceOver के लिए अंतर्निर्मित समर्थन। Apple (WWDC 2024) सभी नए UITableView के लिए contentConfiguration की अनुशंसा करता है।
UITableViewDataSource — एक प्रोटोकॉल जो टेबल के लिए डेटा प्रदान करता है। अनिवार्य विधियाँ: tableView(_:numberOfRowsInSection:) और tableView(_:cellForRowAt:)। इनके बिना, टेबल एक भी पंक्ति प्रदर्शित नहीं कर सकती। UITableViewDelegate — दिखावट और व्यवहार प्रबंधित करने के लिए प्रोटोकॉल: पंक्ति ऊँचाई, चयन, संपादन, प्रासंगिक क्रियाएँ।
// कई अनुभागों और संपादन के साथ उदाहरण
extension ContactListController: UITableViewDelegate {
// प्रत्येक पंक्ति के लिए कस्टम ऊँचाई
func tableView(_ tableView: UITableView,
heightForRowAt indexPath: IndexPath) -> CGFloat {
80
}
// चयन प्रबंधन
func tableView(_ tableView: UITableView,
didSelectRowAt indexPath: IndexPath) {
tableView.deselectRow(at: indexPath, animated: true)
let contact = contacts[indexPath.row]
showDetail(for: contact)
}
// Swipe-to-delete
func tableView(_ tableView: UITableView,
trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath)
-> UISwipeActionsConfiguration? {
let deleteAction = UIContextualAction(style: .destructive, title: "हटाएँ") {
[weak self] _, _, completion in
self?.contacts.remove(at: indexPath.row)
tableView.deleteRows(at: [indexPath], with: .automatic)
completion(true)
}
return UISwipeActionsConfiguration(actions: [deleteAction])
}
}
डेलिगेट प्रदर्शन: आकार विधियाँ (heightForRowAt) प्रत्येक स्क्रॉल पर प्रत्येक दृश्य पंक्ति के लिए कॉल की जाती हैं। समान ऊँचाई के लिए, सीधे rowHeight सेट करें — यह heightForRowAt से 10 गुना तेज़ है। सेल्फ-साइज़िंग सेल्स के लिए, estimatedRowHeight और automaticDimension सेट करें — टेबल केवल दृश्य पंक्तियों के लिए heightForRowAt कॉल करती है और बाकी के लिए estimatedRowHeight का उपयोग करती है।
पुन: उपयोग कतार — पुन: प्रयोज्य UITableView सेल्स का एक पूल। जब कोई सेल स्क्रीन से बाहर स्क्रॉल होती है, तो वह हटाई नहीं जाती बल्कि कतार में रख दी जाती है। नई सेल्स शून्य से नहीं बनाई जातीं — सिस्टम dequeueReusableCell(withIdentifier:for:) कॉल करता है, जो कतार से एक सेल लौटाता है या यदि कतार खाली है तो नई बनाता है। यह UITableView का मुख्य प्रदर्शन तंत्र है।
// कैशिंग के साथ कस्टम सेल
class ContactCell: UITableViewCell {
private let avatarView = UIImageView()
private let nameLabel = UILabel()
private let subtitleLabel = UILabel()
override init(style: UITableViewCell.Style, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
setupViews()
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
private func setupViews() {
contentView.addSubview(avatarView)
contentView.addSubview(nameLabel)
contentView.addSubview(subtitleLabel)
// Auto Layout कंस्ट्रेंट कॉन्फ़िगर करना
avatarView.translatesAutoresizingMaskIntoConstraints = false
// ... constraints ...
}
func configure(with contact: Contact) {
nameLabel.text = contact.name
subtitleLabel.text = contact.phone
// एसिंक्रोनस अवतार लोडिंग
}
override func prepareForReuse() {
super.prepareForReuse()
avatarView.image = nil
nameLabel.text = nil
subtitleLabel.text = nil
}
}
// पंजीकरण और उपयोग
tableView.register(ContactCell.self, forCellReuseIdentifier: "contactCell")
// cellForRowAt में:
let cell = tableView.dequeueReusableCell(withIdentifier: "contactCell", for: indexPath) as! ContactCell
cell.configure(with: contacts[indexPath.row])
return cell
prepareForReuse() — एक विधि जो सेल को पुन: उपयोग कतार में रखने से पहले कॉल की जाती है। सभी सेल स्थिति रीसेट करें: टेक्स्ट, इमेज, एनिमेशन, लोडिंग ऑपरेशन। prepareForReuse के बिना, पुन: उपयोग की गई सेल पुराना डेटा दिखा सकती है: नई इमेज लोड होने तक पिछली इमेज एक सेकंड के अंश के लिए दिखाई देगी। Apple (WWDC 2023) prepareForReuse में URLSessionTask.cancel() के माध्यम से एसिंक्रोनस ऑपरेशन रद्द करने की अनुशंसा करता है।
अनुभाग UITableView में तार्किक रूप से संबंधित पंक्तियों को समूहित करते हैं। प्रत्येक अनुभाग में हेडर और फुटर हो सकता है। अनुभागों की संख्या numberOfSections(in:) विधि द्वारा निर्धारित की जाती है (डिफ़ॉल्ट 1 है)। grouped और insetGrouped शैलियों के लिए, अनुभाग मार्जिन और गोल कोनों द्वारा दृश्य रूप से अलग किए जाते हैं।
| DataSource विधि | विवरण | वापसी मान |
|---|---|---|
| numberOfSections | अनुभागों की संख्या (डिफ़ॉल्ट 1) | Int |
| numberOfRowsInSection | अनुभाग में पंक्तियों की संख्या | Int |
| titleForHeaderInSection | अनुभाग हेडर शीर्षक टेक्स्ट | String? |
| titleForFooterInSection | अनुभाग फुटर शीर्षक टेक्स्ट | String? |
| viewForHeaderInSection | हेडर के लिए कस्टम व्यू | UIView? |
| heightForHeaderInSection | हेडर ऊँचाई | CGFloat |
इंडेक्सिंग: अनुभागों के बीच त्वरित नेविगेशन के लिए, एक इंडेक्स शीर्षक जोड़ें — दाएँ तरफ प्रदर्शित स्ट्रिंग्स की एक सरणी। sectionIndexTitles(for:) लागू करें — प्रत्येक अनुभाग के पहले अक्षरों की एक सरणी लौटाता है। 26+ अनुभागों के लिए, यह UX को महत्वपूर्ण रूप से बेहतर बनाता है। iOS 15+ में, टेबल्स sectionHeaderTopPadding का समर्थन करती हैं — स्टेटस बार और पहले हेडर के बीच पैडिंग, जिसे घने लेआउट के लिए 0 पर रीसेट किया जा सकता है।
प्रदर्शन लंबी सूचियों वाले ऐप्स के लिए UITableView का प्रदर्शन महत्वपूर्ण है। सामान्य समस्याएँ: cellForRowAt में भारी संचालन के कारण धीमी स्क्रॉलिंग (jank), बार-बार heightForRowAt कॉल, prefetching की कमी। Apple (WWDC 2025) 1000+ आइटम वाली टेबल्स के लिए पाँच प्रमुख अभ्यासों पर प्रकाश डालता है।
// Prefetching के साथ अनुकूलन
extension ContactListController: UITableViewDataSourcePrefetching {
func tableView(_ tableView: UITableView,
prefetchRowsAt indexPaths: [IndexPath]) {
for indexPath in indexPaths {
let contact = contacts[indexPath.row]
ImageCache.shared.prefetch(url: contact.avatarUrl)
}
}
func tableView(_ tableView: UITableView,
cancelPrefetchingForRowsAt indexPaths: [IndexPath]) {
for indexPath in indexPaths {
let contact = contacts[indexPath.row]
ImageCache.shared.cancelPrefetch(url: contact.avatarUrl)
}
}
}
// सहज अपडेट के लिए DiffableDataSource का उपयोग
class ModernTableController: UIViewController {
private var dataSource: UITableViewDiffableDataSource<Section, Contact>!
func applyContacts(_ contacts: [Contact]) {
var snapshot = NSDiffableDataSourceSnapshot<Section, Contact>()
snapshot.appendSections([.main])
snapshot.appendItems(contacts)
dataSource.apply(snapshot, animatingDifferences: true)
}
}
व्यावहारिक परिणाम: इन अनुकूलन को लागू करने से iPhone 12 और नए डिवाइसों पर स्क्रॉल FPS 30 से 60 तक बढ़ जाता है (Apple परीक्षण डेटा, 2025 के अनुसार)। IT Sectr परियोजनाओं में, हम सभी नई टेबल्स के लिए DiffableDataSource का उपयोग करते हैं और इमेज वाली टेबल्स (अवतार, पूर्वावलोकन, ऐप आइकन) के लिए prefetching जोड़ते हैं।
अक्सर पूछे जाने वाले प्रश्न
जाँचें: (1) contentSize > frame.size — टेबल में उसकी ऊँचाई से अधिक सामग्री होनी चाहिए; (2) टेबल किसी अन्य UIScrollView के अंदर नहीं है जो जेस्चर को इंटरसेप्ट करता है; (3) isScrollEnabled = true; (4) numberOfRowsInSection सही संख्या लौटाता है। एक सामान्य समस्या estimatedRowHeight के बिना heightForRowAt = UITableView.automaticDimension वाली टेबल है, जो अनंत ऊँचाई गणना का कारण बनती है।
reloadData() के बजाय performBatchUpdates या DiffableDataSource का उपयोग करें। reloadData() बिना एनिमेशन के पूर्ण रीलोड का कारण बनता है, जिससे दृश्य झिलमिलाहट होती है। लक्षित अपडेट के लिए उपयोग करें: reloadRows(at:with:), insertRows, deleteRows। performBatchUpdates के अंदर सभी परिवर्तन एक साथ एनिमेट होते हैं। DiffableDataSource बिना मैन्युअल कॉल के यह स्वचालित रूप से करता है।
UITableView पूर्वनिर्धारित सेल शैलियों और अंतर्निर्मित संपादन के साथ एकल-कॉलम वर्टिकल सूची है। UICollectionView मनमाना तत्व स्थिति निर्धारण के साथ लचीला लेआउट (ग्रिड, सूची, कैरोसेल, वॉटरफॉल) है। सरल सूचियों (सेटिंग्स, संपर्क, संदेश) के लिए UITableView चुनें। गैलरी, कैटलॉग, बोर्ड और किसी भी गैर-रैखिक लेआउट के लिए UICollectionView चुनें।
tableView.tableFooterView = UIView(frame: .zero) सेट करें। डिफ़ॉल्ट रूप से, UITableView अंतिम आइटम के नीचे खाली पंक्तियाँ (सेपरेटर) प्रदर्शित करता है। tableFooterView के रूप में खाली UIView सेट करना उन्हें हटा देता है। grouped शैली के लिए यह आवश्यक नहीं है — टेबल केवल अंतिम अनुभाग पर गोल कोनों के साथ वास्तविक पंक्तियाँ प्रदर्शित करती है।
tableView.rowHeight = 80 और tableView.estimatedRowHeight = 0 सेट करें या estimatedRowHeight छोड़ दें। स्थिर ऊँचाई के साथ, UITableView heightForRowAt कॉल नहीं करता, जो 100+ आइटम वाली सूचियों के लिए रेंडरिंग को 5–10 गुना तेज़ करता है। कस्टम ऊँचाई (अलग सामग्री) वाले सेल्स के लिए, सेल्फ-साइज़िंग का उपयोग करें: estimatedRowHeight + UITableView.automaticDimension।
सारांश
हम एक मोबाइल एप्लिकेशन टर्नकी विकसित करेंगे
IT Sectr 2017 से स्टार्टअप और व्यवसायों के लिए iOS और Android एप्लिकेशन बनाता है। हम आपको सलाह देंगे और सर्वोत्तम समाधान प्रस्तावित करेंगे।