Making a Stateful TableView for iOS
Different States of UITableView
It is pretty much obvious that we often face the following states while loading data for a UITableView
.
- Data is available for the table view.
- Data loaded successfully but the list is empty.
- The server side hung up unexpectedly (😇 It’s my turn to cheer up).
- Application couldn’t reach the server. Request time out(⏱).
- No internet connection at all.
- Any other unknown error(🤔).
In my last two projects, I have faced them a lot. As usual I tried to find out a solution of my own. This led me creating my first ever pod library. That sounds really good(💪).
A light weight wrapper over UITableView:
I finally solved the problem after creating a wrapper on UITableView
. It is basically a sub-class of UITableView
with a few utility method to show proper message depending upon the states of the table view I mentioned above.
How to start ?
Create a single view project using Xcode and install the following pod library using cocoapods
. If you are repetitively facing the following error while installing executing pod init
-bash: /usr/local/bin/pod: /System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/bin/ruby: bad interpreter: No such file or directory
you need to reinstall pods on macOS High Sierra using
sudo gem install cocoapods`
Now include SDStateTableView in your Podfile
.
pod 'SDStateTableView'
Once you have completed the installation using pod install
command, you need to open up the .xcworkspace
file on Xcode.
If you face any problem installing the pod, you can download the starter project from GitHub.
If everything was fine, you can replace your project’s Assets.xcassets
with the required assets from GitHub. It contains some assets to show on table view depending upon the state.
Sorry, I am not going to show you how I used this library in my client project with original data sets. But I promise that you will be able to handle all the states I mentioned above for a UITableView.
Let’s Build the Basic UI:
Open the Main.storyboard
file. Let’s drag and drop a UITableView
from the UI Library section on the View Controller Scene with the following constraints.
Adding a TableView and settings up layout constraints
Now select the table view from Document Out Line Area, open up the Identity Inspector and set the class of this table view to SDStateTableView
. Add a prototype cell and set TableViewCell
as the reusable identifier for it. Do not forget to set the ViewController as the data source of the TableView.
It’s time to add some buttons to play with the table view. Add six buttons in two UIStackView
s in such a way the final layout will be similar to the following one. We are going to change the state of table view on tap on those events.
Adding button stack and it’s constraints
It’s time to add some code:
Now open ViewController.swift
and add the import statement import SDStateTableView
just bellow the import UIKit line
. Create an IBOutlet for the table view named stateTableView
.
@IBOutlet weak var stateTableView: SDStateTableView!
Now for handling touch on the six buttons add the following IBAction
s in the ViewController.swift
file.
// MARK: IBActions
extension ViewController {
@IBAction func dataAvailableButtonTapped(_ sender: UIButton) {
}
@IBAction func noDataAvailableButtonTapped(_ sender: UIButton) {
}
@IBAction func errorWithImageButtonTapped(_ sender: UIButton) {
}
@IBAction func errorWithTitleButtonTapped(_ sender: UIButton) {
}
@IBAction func loadingDataButtonTapped(_ sender: UIButton) {
}
@IBAction func noInternetButtonTapped(_ sender: UIButton) {
}
}
Showing Data on TableView:
To show some data on the tableview, we will be implementing the UITableViewDataSource
methods in the following way.
// MARK: - UITableViewDataSource Methods
extension ViewController: UITableViewDataSource {
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView,
numberOfRowsInSection section: Int) -> Int {
switch (tableView as! SDStateTableView).currentState { case .dataAvailable: tableView.separatorStyle = .singleLine return 14 default: tableView.separatorStyle = .none return 0 }
}
func tableView(_ tableView: UITableView,
cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "TableViewCell")
cell?.textLabel?.text = "Row number \(indexPath.row)"
return cell!
}
}
There is nothing special in those lines of code except the bold area. I am only enabling separator style to my default one ( .singleLine ), only when there is data for the table view, otherwise seperator style is .none.
How do I manage the states?
The wait is over, we are almost done with coding except the following modifications to the IBAction
methods. Lets do that.
That’s it we are all done. Let’s run the project and see what’s happening.
Final output:
Final output
You can find the completed project at GitHub. If you love this blog, don’t forget to give a clap!
Promotions:
Don’t forget to read my other blogs😏.