Swipeable table view cell with custom editable views in iOS

Hello guys, I decided to write a short post related to one of the UI issues, some of my colleges faced during implementing UITableView cell actions with custom UIViews. For my convenience, I wrote the sample project in Swift 5. iOS has given the developer to edit the table cells, but it’s hard to change the editable view. As an example, if we were asked to have lengthy text in single line or image and a label in side by side etc…

You can come up with various designs for editable actions. But I’m going to implement the above mentioned two approaches. The final outcome will be like below.

Swipe-able UITableViewCell with custom edit views

Swipe-able UITableViewCell with custom edit views

As for the start, just create an iOS project and in your ViewController in the storyboard, add an UITableView and set it’s constraints to margin of the super view. Next thing you have to do is, create a custom UITableViewCell class. As for my convenience, I’ll put the whole code related to that class in below. I have described what each function will perform in the comments.

import UIKit

class SwipableTableViewCell: UITableViewCell, UIScrollViewDelegate {

    var scrollView: UIScrollView?
    var scrollViewContentView: UIView?
    var scrollViewLabel: UILabel?
    let kCellCloseNotifyEvent = "SwipeableTableViewCellClose"
    var leftInset: CGFloat?
    var rightInset: CGFloat?

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)

    override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
        super.init(style: style, reuseIdentifier: reuseIdentifier)
    override func layoutSubviews() {
        self.scrollView?.contentSize = self.contentView.bounds.size
        self.scrollView?.contentOffset = CGPoint.zero

    //    MARK: UIScrollViewDelegate
     *  When a cell's editable action reveals, other cells editable actions should be clase
    func scrollViewWillBeginDragging(_ scrollView: UIScrollView) {
        closeAllCellsExcept(cell: self)
     *  Restricting scroll to right side where there is not action elements
    func scrollViewDidScroll(_ scrollView: UIScrollView) {
        if (scrollView.contentOffset.x < 0) {
            scrollView.contentOffset = CGPoint(x: 0, y: 0);

    //    MARK: Notification selectors
    @objc func handleCloseEvent(notification: Notification) {
        self.scrollView?.setContentOffset(CGPoint.zero, animated: true)

    //    MARK: Supportive methods

     *  Create cell the cell with horizontally scorllable behaviour
    func setUp() {
        let scrollView = UIScrollView(frame: self.contentView.bounds)
        scrollView.autoresizingMask = AutoresizingMask(rawValue: AutoresizingMask.flexibleWidth.rawValue | AutoresizingMask.flexibleHeight.rawValue)
        scrollView.contentSize = self.contentView.bounds.size
        scrollView.delegate = self
        scrollView.scrollsToTop = false
        scrollView.showsHorizontalScrollIndicator = false
        scrollView.showsVerticalScrollIndicator = false
        self.scrollView = scrollView

        let contentView = UIView(frame: scrollView.bounds)
        contentView.autoresizingMask = AutoresizingMask(rawValue: AutoresizingMask.flexibleWidth.rawValue | AutoresizingMask.flexibleHeight.rawValue)
        self.scrollViewContentView = contentView
        let label = UILabel(frame: CGRect(x: 20, y: contentView.bounds.size.height/2, width: contentView.bounds.size.width, height: 0))
        label.autoresizingMask = AutoresizingMask(rawValue: AutoresizingMask.flexibleWidth.rawValue | AutoresizingMask.flexibleHeight.rawValue)
        self.scrollViewLabel = label
        NotificationCenter.default.addObserver(self, selector: #selector(self.handleCloseEvent(notification:)), name: NSNotification.Name(rawValue: kCellCloseNotifyEvent), object: nil)

     *  View that holds the editable actions
    func createCustomViewContainer() -> UIView {
        let view = UIView(frame: CGRect(x: 0, y: 0, width: 0, height: self.contentView.bounds.size.height))
        view.autoresizingMask = AutoresizingMask(rawValue: AutoresizingMask.flexibleHeight.rawValue)
        view.backgroundColor = UIColor.lightGray
        return view

     *  Create cell editable action that contains only a button
    func createButtonWithWidth(width: CGFloat) -> UIButton {

        let container: UIView = createCustomViewContainer()
        let size = container.bounds.size
        let button = UIButton(type: UIButton.ButtonType.custom)
        button.autoresizingMask = AutoresizingMask(rawValue: AutoresizingMask.flexibleHeight.rawValue)
        button.frame = CGRect(x: 0, y: 0, width: width, height: size.height)
        container.frame = CGRect(x: UIScreen.main.bounds.size.width, y: 0, width: size.width + width, height: size.height)
        self.scrollView?.contentInset = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 160)
        return button

     *  Create cell editable action that contains an image and a label
    func createViewWithImageAndLabel(width: CGFloat) -> UIView {

        let container: UIView = createCustomViewContainer()
        let size = container.bounds.size

        let imageName = "Notification"
        let image = UIImage(named: imageName)
        let imageView = UIImageView(image: image!)
        imageView.contentMode = .scaleAspectFit
        imageView.frame = CGRect(x: 0, y: 10, width: 100, height: size.height)

        let label = UILabel(frame: CGRect(x: imageView.bounds.size.width, y: 10, width: 100, height: size.height))
        label.textAlignment = .center
        label.text = "Notify Me"

        container.frame = CGRect(x: UIScreen.main.bounds.size.width, y: 0, width: width, height: size.height)

        self.scrollView?.contentInset = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 200)
        return imageView

     *  Close all opened cell
     *      If argument comes as self, keep that cell open but close the others
    func closeAllCellsExcept(cell: SwipableTableViewCell) {
        NotificationCenter.default.post(name: NSNotification.Name(rawValue: kCellCloseNotifyEvent), object: cell)

     *  When table start scrolling, we need to close all the opened cells
    func closeAllCells() {
        closeAllCellsExcept(cell: SwipableTableViewCell())

Yep, that’s the magic. Now you have to call that custom cell inside your tableView cellForRowAt function like below.

 func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

        let cell = SwipableTableViewCell(style: UITableViewCell.CellStyle.default, reuseIdentifier: cellIdentifier)
        cell.backgroundColor = UIColor.white
        cell.scrollViewLabel?.text = dataArray[indexPath.row]
        if (indexPath.row % 2 == 0) {
            let moreButton = cell.createButtonWithWidth(width: 160)
            moreButton.setTitle("Do not notify me", for: UIControl.State.normal)
            moreButton.setTitleColor(UIColor.white, for: UIControl.State.normal)
            moreButton.titleLabel?.textAlignment = NSTextAlignment.center
            moreButton.addTarget(self, action: #selector(notifyMe), for: UIControl.Event.touchUpInside)
        else {
            _ = cell.createViewWithImageAndLabel(width: 200)
        return cell

To enable cell edit, add following code in your controller, where you are declaring UITableViewDelegates.

func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
    return true

To close the open cells when you scroll the table, just add following function by implementing UIScrollViewDelegate in your ViewController class.

func scrollViewWillBeginDragging(_ scrollView: UIScrollView) {

I think that is pretty much that you need to know. This is not a complex code. What’s difficult was think out of the box and create the cell behaviour as in the default UITableViewCell. But my point is, we need to think twice when we add this kind of custom components in industry level apps. Because the effort and the time we spent on this should be worth. For those who needs full project, can access here. Have a interesting coding time till we meet again 🙂



About AnujAroshA

Working as a Technical Lead. Specialized in iOS application development. A simple person :)
This entry was posted in iOS, Swift and tagged , , . Bookmark the permalink.

2 Responses to Swipeable table view cell with custom editable views in iOS

  1. Sabari says:

    hi, the content is really useful. I have also implemented the same scrollview like cell. But when I use the cell in the tableview, the delegate of didSelectRow is not called. Please let me know, if you know the solution for this issue

  2. Sabari says:

    hi, while using this in a tableview, I can scroll multiple items at a time, and on disabling tableview multitouch option also I face the same problem, can I get any solution for this

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 )

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