Sunday, March 20, 2016

Overview

This post will show you how to add a custom swipe action to your TableViewCells. I was trying out Ray’s guide to swipable cells and wanted to make a post that about the least amount of code needed to make a swipable cell.

Content

We need 3 classes.

  • TableViewCellDelegate
  • UITableViewCell
  • UITableViewController

Assuming that you’ve already created a working TableViewController from my TableView post, we can get started.

TableViewCellDelegate

Let’s start with the delegate since it’s so simple. We’ll make the TableView conform to this protocol and pass it to the TableViewCell. We detect a swipe inside the TableViewCell and then using the delegate, tell the TableView.

1
2
3
4
5
6
import UIKit

protocol TableViewCellDelegate {
    // tell the TableView that a swipe happened
    func hasPerformedSwipe(passedInfo: String)
}

UITableViewCell

We need the following methods in this class:

  • initialize: to add the gesture recognizer for swiping
  • handlePan: to handle the swiping
  • checkIfSwiped: to check if a swipe was performed
  • moveViewBackIntoPlace: to move the cell back in place
  • gestureRecognizerShouldBegin: to only let the swipe work horizontally

Create the class and add it as the custom class of your TableViewCell in StoryBoard or in code.

Title

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import UIKit

class MyTableViewCell: UITableViewCell {
    var delegate: TableViewCellDelegate?
    var originalCenter = CGPoint()
    var isSwipeSuccessful = false

    @IBOutlet weak var titleLabel: UILabel!

    override func awakeFromNib() {
        super.awakeFromNib()
        initialize()
    }

    func initialize() {}
    func handlePan(recognizer: UIPanGestureRecognizer) {}
    func checkIfSwiped(recognizer: UIPanGestureRecognizer) {}
    func moveViewBackIntoPlace(originalFrame: CGRect) {}
    override func gestureRecognizerShouldBegin(gestureRecognizer: UIGestureRecognizer) -> Bool {}
}

In initialize, we add the gesture recongnizer. In checkIfSwiped, we translate the cell and see if we moved more than 50% of the cell’s width. In moveViewBackIntoPlace, we just move back the cell into it’s original position.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
func initialize() {
    let recognizer = UIPanGestureRecognizer(target: self, action: "handlePan:")
    recognizer.delegate = self
    addGestureRecognizer(recognizer)
}

func checkIfSwiped(recongizer UIPanGestureRecognizer) {
    let translation = recognizer.translationInView(self)
    center = CGPointMake(originalCenter.x + translation.x, originalCenter.y)
    isSwipeSuccessful = frame.origin.x > frame.size.width / 2.0
}

func moveViewBackIntoPlace(originalFrame: CGRect) {
    UIView.animateWithDuration(0.2, animations: {self.frame = originalFrame})
}

Our pan should recognize horizontal swipes only. It doesn’t right now. Let’s fix that.

1
2
3
4
5
6
7
8
9
override func gestureRecognizerShouldBegin(gestureRecognizer: UIGestureRecognizer) -> Bool {
    if let panGestureRecognizer = gestureRecognizer as? UIPanGestureRecognizer {
        let translation = panGestureRecognizer.translationInView(superview!)
        if fabs(translation.x) > fabs(translation.y) {
            return true
        }
    }
    return false
}

Let’s add the swipe code.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
func handlePan(recognizer: UIPanGestureRecognizer) {
    if recognizer.state == .Began {
        originalCenter = center
    }
    
    if recognizer.state == .Changed {
        checkIfSwiped(recognizer)
    }

    if recognizer.state == .Ended {
        let originalFrame = CGRect(x: 0, y: frame.origin.y,
            width: bounds.size.width, height: bounds.size.height)
        if isSwipeSuccessful, let delegate = self.delegate {
            delegate.cardEdit("I performed a swipe")
        } else {
            moveViewBackIntoPlace(originalFrame)
        }
    }
}

UITableViewController

Add the protocol TableViewCellDelegate to the class and implement the method hasPerformedSwipe.

1
2
3
4
5
6
7
8
func hasPerformedSwipe(passedInfo: String) {
    let alert = UIAlertController(title: "Works", 
                        message: passedInfo, 
                        preferredStyle: UIAlertControllerStyle.Alert)
    let defaultAction = UIAlertAction(title: "OK", style: .Default, handler: nil)
    alert.addAction(defaultAction)
    presentViewController(alert, animated: true, completion: nil)
}

Title


Random Posts