如何实现可滑动切换的动态UITableView Todo App:多日数据展示方案
Great question! For your Todo app that needs swipeable, dynamically-controlled UITableViews tied to date-specific data arrays, the best approach is to use a horizontal UICollectionView where each collection view cell embeds a UITableView. This setup is lightweight, memory-efficient, and makes it trivial to control the number of "date pages" based on your data array.
Core Concept
Each item in the horizontal UICollectionView represents a single date's page. Inside each collection cell, we'll embed a UITableView that displays the todo items from the corresponding subarray in your testArray. The number of pages is automatically determined by the count of testArray—so adding/removing dates just requires updating the array.
Step-by-Step Implementation
1. Define the Collection View Cell with Embedded UITableView
First, create a custom collection cell that holds the UITableView and manages its data:
class TodoDayCell: UICollectionViewCell { // Embedded table view for todo items private let tableView = UITableView() // Data source for this date's todos var dayTodos: [String] = [] { didSet { tableView.reloadData() } } override init(frame: CGRect) { super.init(frame: frame) configureTableView() } required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } private func configureTableView() { tableView.frame = contentView.bounds tableView.autoresizingMask = [.flexibleWidth, .flexibleHeight] tableView.dataSource = self // Register a default cell (replace with custom cell if needed) tableView.register(UITableViewCell.self, forCellReuseIdentifier: "TodoItemCell") contentView.addSubview(tableView) } } // MARK: - UITableView Data Source extension TodoDayCell: UITableViewDataSource { func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { dayTodos.count } func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "TodoItemCell", for: indexPath) cell.textLabel?.text = dayTodos[indexPath.row] return cell } }
2. Set Up the Main View Controller with Horizontal Collection View
Next, create the main view controller that manages the collection view and connects it to your data array:
class TodoMainViewController: UIViewController { // Your dynamic data array (update this to add/remove date pages) var testArray = [ ["Day0-0","Day0-1","Day0-2"], ["Day1-0","Day1-1","Day1-2"], ["Day2-0","Day2-1","Day2-2"] ] private let collectionView: UICollectionView override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) { // Configure horizontal flow layout for full-screen pages let layout = UICollectionViewFlowLayout() layout.scrollDirection = .horizontal layout.itemSize = UIScreen.main.bounds.size layout.minimumLineSpacing = 0 collectionView = UICollectionView(frame: .zero, collectionViewLayout: layout) super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil) setupCollectionView() } required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } override func viewDidLoad() { super.viewDidLoad() view.backgroundColor = .systemBackground } private func setupCollectionView() { collectionView.frame = view.bounds collectionView.autoresizingMask = [.flexibleWidth, .flexibleHeight] collectionView.dataSource = self collectionView.register(TodoDayCell.self, forCellWithReuseIdentifier: "TodoDayCell") // Enable paging for smooth page-swiping behavior collectionView.isPagingEnabled = true view.addSubview(collectionView) } } // MARK: - UICollectionView Data Source extension TodoMainViewController: UICollectionViewDataSource { func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { // Dynamically return the number of date pages testArray.count } func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "TodoDayCell", for: indexPath) as! TodoDayCell // Pass the corresponding subarray to the cell cell.dayTodos = testArray[indexPath.item] return cell } }
Why This Works Better Than Alternatives
- Dynamic Control: The number of table views is directly tied to
testArray.count—update the array, callcollectionView.reloadData(), and the UI automatically adjusts. - Memory Efficiency: UICollectionView reuses cells, so you won't have all table views loaded into memory at once (critical if you have many date pages).
- Smooth Swiping: The
isPagingEnabledproperty gives you natural page-aligned swiping, just like a date-based app should have. - Clean Separation: Each cell manages its own table view and data, keeping your code organized and avoiding messy global state.
Optional Enhancements
- Add a
UIPageControlto let users see their current position among date pages. - Implement custom
UITableViewCellsubclasses to style your todo items with checkboxes, due dates, etc. - Use batch updates (
collectionView.performBatchUpdates(_:completion:)) instead of full reloads when adding/removing date pages for smoother animations.
内容的提问来源于stack exchange,提问作者Jort Boon

