TTBaseUITableView
CorePre-configured UITableView subclass with auto-dimension row heights, automatic keyboard dismiss on scroll, navigation bar content inset, thread-safe async reload, and visible-row-only reload helpers. Works seamlessly with TTBaseUIViewController.
🏗 Initializers
// Plain style, clear background
let tableView = TTBaseUITableView(frame: .zero, style: .plain)
// Grouped style, with all options
let settingsTable = TTBaseUITableView(
style: .grouped,
bgColor: .systemGroupedBackground,
isShowCroll: false, // hide scroll indicators
isSetContent: false // no top content inset (no nav bar offset)
)
🚀 Usage
Standard Setup in a ViewController
class ProductListVC: TTBaseUIViewController {
// Table with automatic row height
lazy var tableView: TTBaseUITableView = {
let t = TTBaseUITableView(frame: .zero, style: .plain)
t.register(ProductCell.self, forCellReuseIdentifier: "ProductCell")
t.dataSource = self
t.delegate = self
return t
}()
override func setupConstraints() {
tableView.setFullContraints(constant: 0)
}
}
Reload Data (Thread-Safe)
// Ensures reloadData() runs on main thread
viewModel.onDataLoaded = { [weak self] in
self?.tableView.reloadAsyncData()
}
// Reload only visible rows that need updating
let newIndexPaths = [IndexPath(row: 2, section: 0)]
tableView.reloadAsyncRows(with: newIndexPaths, animation: .fade)
Visible + Pending Reload (Pagination)
// Only reload rows that are both in newIndexPaths AND currently visible
// Avoids reloading off-screen rows unnecessarily
let visible = tableView.visibleIndexPathsToReload(
intersecting: newIndexPaths
)
tableView.reloadAsyncRows(with: visible)
Content Inset Management
// Remove auto top inset (when no navigation bar)
tableView.resetContentInset()
// Set custom inset
tableView.setContentInset(
inset: UIEdgeInsets(top: 0, left: 0, bottom: 80, right: 0)
)
📖 API Reference
| Method / Property | Returns | Description |
|---|---|---|
bgColor | UIColor | Background color (default: clear) |
isShowScrollIndicator | Bool | Show/hide scroll indicators (default: false) |
isSetContentInset | Bool | Auto-add top inset = H_NAV for nav bar (default: true) |
reloadAsyncData() | Void | Thread-safe reloadData() on main queue |
reloadAsyncRows(with:animation:) | Void | Reload specific rows safely (skips non-existing cells) |
visibleIndexPathsToReload(intersecting:) | [IndexPath] | Filter new index paths to only visible rows |
setContentInset(inset:) | Void | Set custom content inset |
resetContentInset() | Void | Reset content inset to zero |
⚙️ Auto Behaviour
| Feature | Default | Control |
|---|---|---|
| Row height | automaticDimension | Set estimatedRowHeight on your cell |
| Keyboard dismiss | On scroll (keyboardDismissScrollViewType) | StyleConfig.dismissKeyboardScrollViewType |
| Section header top padding | 0 (iOS 15+) | Automatic |
| Top content inset | H_NAV (for nav bar) | Set isSetContentInset: false |
| Scroll indicators | Hidden | Set isShowCroll: true |
Pro Tip: Combine
visibleIndexPathsToReload(intersecting:) with pagination to avoid expensive full reloads — only cells the user can see get refreshed, keeping animations smooth.