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 অ্যাপ্লিকেশন তৈরি করে। আমরা আপনাকে পরামর্শ দেব এবং সেরা সমাধান প্রস্তাব করব।