In the realm of iOS development, understanding how to create a UITableView is a fundamental skill. In this tutorial, I'll guide you through the process of setting up a basic UITableView entirely through code, omitting the use of storyboards. We'll also explore the concept of using a ViewModel to manage data efficiently. By the end of this tutorial, you'll be equipped with the knowledge to construct dynamic and organized lists in your iOS applications.
Step 1: Designing the UI Programmatically
Begin by designing your user interface programmatically in the view controller. We'll replace the storyboard-based setup with code. To remove storyboards completely from your project, follow these steps. Here, we're creating a UITableView property and configuring it within the viewDidLoad method.
import UIKit
class YourViewController: UIViewController {
var tableView: UITableView = {
let tableView = UITableView()
tableView.translatesAutoresizingMaskIntoConstraints = false
return tableView
}()
var viewModel: YourViewModel
init(viewModel: YourViewModel) {
self.viewModel = viewModel
super.init(nibName: nil, bundle: nil)
}
// Required initializer for UIViewController
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .white
setupTableView()
}
private func setupTableView() {
view.addSubview(tableView)
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) ])
}
}
Step 2: Create a ViewModel
Just as before, create a ViewModel to handle your data. For simplicity, we've included a sample ViewModel (YourViewModel) that populates an array with sample content.
import Foundation
class YourViewModel {
var data: [String] = []
init() {
data = ["Item 1", "Item 2", "Item 3", "Item 4"]
}
}
Step 3: Implement UITableViewDataSource and UITableViewDelegate
Adopt the UITableViewDataSource and UITableViewDelegate protocols within your view controller. These protocols dictate how the UITableView should be populated and how it should respond to user interactions.
class YourViewController: UIViewController {
private func setupTableView() {
view.addSubview(tableView)
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) ])
// Set delegate and dataSource to this ViewController
tableView.delegate = self
tableView.dataSource = self
}
}
}
extension YourViewController: UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return viewModel.data.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = UITableViewCell(style: .default, reuseIdentifier: "YourCellIdentifier")
cell.textLabel?.text = viewModel.data[indexPath.row]
return cell
}
}
extension YourViewController: UITableViewDelegate {
// Implement UITableViewDelegate methods as needed
}
Step 4: Run Your App
Build and run your app. You should now observe a simple UITableView populated with data, all created programmatically without the use of storyboards.
Enhancing with a Custom Cell:
To take your UITableView to the next level, consider using a custom cell for a more personalized appearance. In our example, we've created a YourCustomCell class that inherits from UITableViewCell. This custom cell allows you to tailor the cell layout and appearance to match your app's design.
Here's a quick overview of the steps:
Create YourCustomCell Class:
import UIKit
class YourCustomCell: UITableViewCell {
private let customLabel: UILabel = {
let label = UILabel()
label.translatesAutoresizingMaskIntoConstraints = false
return label
}()
overrideinit(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
setupUI()
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func configure(with text: String) {
customLabel.text = text
}
private func setupUI() {
// Add the label to the cell's content view
contentView.addSubview(customLabel)
// Set up constraints for the label
NSLayoutConstraint.activate([
customLabel.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 8),
customLabel.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 16),
customLabel.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -16),
customLabel.bottomAnchor.constraint(equalTo: contentView.bottomAnchor, constant: -8)
])
}
}
Update YourViewController:
// Register your custom cell class
tableView.register(YourCustomCell.self, forCellReuseIdentifier: "YourCellIdentifier")
// Dequeue your custom cell
let cell = tableView.dequeueReusableCell(withIdentifier: "YourCellIdentifier", for: indexPath) as! YourCustomCell
The entire ViewController will now look like this:
Now, update the YourViewController to use the custom cell:
import UIKit
class YourViewController: UIViewController {
var tableView: UITableView = {
let tableView = UITableView()
tableView.translatesAutoresizingMaskIntoConstraints = false
return tableView
}()
var viewModel: YourViewModel
init(viewModel: YourViewModel) {
self.viewModel = viewModel
super.init(nibName: nil, bundle: nil)
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .white
setupTableView()
}
private func setupTableView() {
view.addSubview(tableView)
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) ])
// Register your custom cell class
tableView.register(YourCustomCell.self, forCellReuseIdentifier: "YourCellIdentifier")
tableView.delegate = self
tableView.dataSource = self
}
}
extension YourViewController: UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return viewModel.data.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
// Dequeue your custom cell
let cell = tableView.dequeueReusableCell(withIdentifier: "YourCellIdentifier", for: indexPath) as! YourCustomCell
cell.configure(with: viewModel.data[indexPath.row])
return cell
}
}
extension YourViewController: UITableViewDelegate {
// Implement UITableViewDelegate methods as needed
}
By incorporating a custom cell, you gain greater control over the visual presentation of each table view cell, allowing you to create a more polished and unique user interface.
You've successfully set up a UITableView in Swift, leveraging a ViewModel and creating the entire UI programmatically. This approach enhances code maintainability and scalability. Feel free to extend the functionality by incorporating additional UITableViewDelegate methods for handling row selection or exploring customization options. Happy coding!
Comments