Codementor Events

Making a Stateful TableView for iOS

Published Jun 29, 2018


Different States of UITableView

It is pretty much obvious that we often face the following states while loading data for a UITableView.

  1. Data is available for the table view.
  2. Data loaded successfully but the list is empty.
  3. The server side hung up unexpectedly (😇 It’s my turn to cheer up).
  4. Application couldn’t reach the server. Request time out(⏱).
  5. No internet connection at all.
  6. 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 UIStackViews 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 IBActions 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😏.

1. Network reachability status monitoring on iOS

  1. Part 1.
  2. Part 2 .

2. A Smart Way to Manage Colour Schemes for iOS Application Development.

3. Handling Fonts in iOS Development, a Simpler Way.

4. Developing a Tiny Logger in Swift.

5. A few git tricks & tips.

Discover and read more posts from Sauvik Dolui
get started
post commentsBe the first to share your opinion
Show more replies