Actions in Table Views

Sometimes table views could use a few buttons. There’s two delegates which create swipe buttons on table view cells. Let’s learn how you can implement these buttons and an interesting hidden feature you can do with them. 

There is two delegate methods, one for the leading swipe configuration and one for the trailing Swipe configuration. They work identically, so I’ll start with the trailing one. 

In the TableViewController.swift code, under the titleForHeaderInsection delegate method,  add the following which you can find in the auto complete: 

override func tableView(_ tableView: UITableView, trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? {
}

}

This method returns  a UISwipeActionsConfiguration, and I’ll add the returned object to my code: 

return UISwipeActionsConfiguration(actions: [greenAction,blueAction])

You’ll see the initializer takes an array of actions of type UIContextualAction. That’s the core of this method.  It sets the title on the cell for your action and handles the code when tapped. I’ll add an action called greenAction

let greenAction = UIContextualAction(style: .normal, title: "Green") { (action, view, actionPerformed) in
         
        }

You’ve got normal and destructive styles for the buttons since you can place code to delete the cell here. I’m just going to leave it .normal then set the title to Green and then add the handler.  

The handler has three parameters: the action itself if you want to change the action, the view in which the action is displayed, and a bool indicating if the action was performed or not.

I made a method for use within the action to change the cell:

//A simple example of what you can do in the cell
    func setCell(color:UIColor, at indexPath: IndexPath){
        
        // I can change external things
        self.view.backgroundColor = color
        // Or more likely change something related to this cell specifically.
        let cell = tableView.cellForRow(at: indexPath )
        cell?.backgroundColor = color
    }

Inside the closure for the action,  I’ll add the setCell method to change the background and cell color. 

let greenAction = UIContextualAction(style: .normal, title: "Green") { (action, view, actionPerformed) in
            self.setCell(color: .green, at: indexPath)
        }

I can change properties of the action as well, including its title and background color. I’ll change the background color to green. 

greenAction.backgroundColor = .green

I’ll copy then paste all this. to make another button, changing all the greens to blues. 

 let blueAction = UIContextualAction(style: .normal, title: "Blue") { (action, view, actionPerformed) in
            self.setCell(color: .blue, at: indexPath)
        }
        blueAction.backgroundColor = .blue

I can take both these actions and place them in the actions array of UISwipeActionsConfiguration

return UISwipeActionsConfiguration(actions: [greenAction,blueAction])

Since the leading version is identical to the trailing version, I’ll copy all of this then  paste it below the first. Change trailing to leading.

override func tableView(_ tableView: UITableView, leadingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? {
        let greenAction = UIContextualAction(style: .normal, title: "Green") { (action, view, actionPerformed) in
            self.setCell(color: .green, at: indexPath)
        }
        greenAction.backgroundColor = .green
        
        let blueAction = UIContextualAction(style: .normal, title: "Blue") { (action, view, actionPerformed) in
            self.setCell(color: .blue, at: indexPath)
        }
        blueAction.backgroundColor = .blue
        
        return UISwipeActionsConfiguration(actions: [greenAction,blueAction])
    }

Build and run using an iPhone XR simulator. If you swipe a cell slowly about 1/4 to 1/2 across right to left, you’ll get the blue and the green trailing button. 

If you swipe gently on another row left to right, you get the green and blue button. 

The first button is the one closest to the leading or trailing edge. Click the green button and the background turns green,  tap the blue button and the background turns blue. 

Now swipe from right to left across the entire button.

The background goes green. The first action of the UISwipeActionsConfiguration will fire on a big swipe. So If I want blue on the leading swipe and green on the trailing ‘Ill change my leading array to have the blue as th first element of the array: 

return UISwipeActionsConfiguration(actions: [blueAction,greenAction])

Run again, and you get the long swipe of blue from the leading and green from the trailing.

This is a powerful, simple,  and useful way to get actions into individual table view cells.  

The Whole Code

Here’s the code for this lesson. You can also download it from Github Here.

//
//  TableViewController.swift
//  SwipeActions
//
//  An exercise file for iOS Development Tips Weekly
//  by Steven Lipton (C)2018, All rights reserved
//  For videos go to http://bit.ly/TipsLinkedInLearning
//  For code go to http://bit.ly/AppPieGithub
//

import UIKit

class TableViewController: UITableViewController {

    let rowCount = 12
    
    override func tableView(_ tableView: UITableView, trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? {
        let greenAction = UIContextualAction(style: .normal, title: "Green") { (action, view, actionPerformed) in
            self.setCell(color: .green, at: indexPath)
        }
        greenAction.backgroundColor = .green
        
        let blueAction = UIContextualAction(style: .normal, title: "Blue") { (action, view, actionPerformed) in
            self.setCell(color: .blue, at: indexPath)
        }
        blueAction.backgroundColor = .blue
        
        return UISwipeActionsConfiguration(actions: [greenAction,blueAction])
    }
    
    override func tableView(_ tableView: UITableView, leadingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? {
        let greenAction = UIContextualAction(style: .normal, title: "Green") { (action, view, actionPerformed) in
            self.setCell(color: .green, at: indexPath)
        }
        greenAction.backgroundColor = .green
        
        let blueAction = UIContextualAction(style: .normal, title: "Blue") { (action, view, actionPerformed) in
            self.setCell(color: .blue, at: indexPath)
        }
        blueAction.backgroundColor = .blue
        
        return UISwipeActionsConfiguration(actions: [blueAction,greenAction])
    }
    
    //A simple example of what you can do in the cell
    func setCell(color:UIColor, at indexPath: IndexPath){
        
        // I can change external things
        self.view.backgroundColor = color
        // Or more likely change something related to this cell specifically.
        let cell = tableView.cellForRow(at: indexPath )
        cell?.backgroundColor = color
    }
    
    
    //Your standard Table Delegate and Data Source methods
    override func numberOfSections(in tableView: UITableView) -> Int {
        return 1
    }
    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return rowCount
    }
    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
        cell.textLabel?.text = String(format:"Row #%i",indexPath.row + 1)
        cell.textLabel?.font = UIFont(name: "GillSans-Bold", size: 26)
        return cell
    }
    
    override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
        return "Sample Action Table"
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
    }
}


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.