Beautifull way of having a multi-selection table on iOS

Swift 5.1 Xcode 11.2.1+ Platforms iOS Licence MIT

Based on this dribbble by Vitaly Rubtsov

How it works:

MultiSelectionTable underneath is composed of a view and a data source, much like the UITableView‘s UITableViewDataSource/Delegate. They both know each other and communicate between themselves. The view is is composed by two configurable UITableView and a line seperating them. The DataSource keeps the data the UITableViews display.


(before Usage, pay attention to the following considerations)

  • In order to achieve a nice effect when transitioning, cells on the right (selected cells) must be equal to the cells on the left (all items cells).
  • The item object you are displaying, must conform with the Equatable protocol so the control can know where to move the items when unselecting items. -You can also paginate and use search on your items list. The table keeps a reference to the selected items.
  • The Marvel developers API has a 3000 requests limit per day. If this is reached and you can’t try the Marvel example, you need to create a developers account to get credentials. Then replace them in Heroes.Fetcher.swift file


Most basic usage:

Considering you are using MultiSelectionTableView in ViewController:

var multiSelectionDataSource: MultiSelectionDataSource<MyItem>! //MyItems must be Equatable
var multiSelectionTableView: MultiSelectionTableView!

var allItems: [MyItem] = [] //MyItem must be Equatable

override func viewDidLoad() {

     multiSelectionTableView = MultiSelectionTableView()

     multiSelectionDataSource = MultiSelectionDataSource(multiSelectionTableView: multiSelectionTableView)
     multiSelectionDataSource.delegate = self
     let cellReuseIdentifier = "MyCell"
     multiSelectionDataSource.register(nib: UINib(nibName: "MyCustomCellNibName", bundle: nil), for: cellReuseIdentifier)

     multiSelectionDataSource.allItems = allItems

     multiSelectionTableView.dataSource = multiSelectionDataSource

extension ViewController : MultiSelectionTableDelegate {

    func paint(_ cell: UITableViewCell, for indexPath: IndexPath, with item: Any) {
        if let cell = cell as? MyCustomCell,
            let myItem = item as? MyItem {



Colors style

multiSelectionTableView.controlBackgroundColor = .black
multiSelectionTableView.allItemsTableBackgroundColor = .black
multiSelectionTableView.selectedItemsTableBackgroundColor = .black

Horizontal movement width:

Depending on your cell, you might want to set the horizontal width the line moves. This value is based on the center X anchor.

multiSelectionTableView.seperatorWidthOffset = 100 //will move 100 point on both directions from the center


There are two animation types. The selection and the transition. You can customize your animations for both types. The default selection animation is a pulse starting on the tap point on the cell. The default transition animation moves a snapshot view of the selected cell to the corresponding side (depending on selection or unselection events)

multiSelectionTableView.cellAnimator = CellSelectionPulseAnimator(pulseColor: .black) // Must conform to CellSelectionAnimator
multiSelectionTableView.cellTransitioner = CellFlyerAnimator() // Must conform to CellTransitionAnimator

You can check out the animator examples.


If you want MultiSelectionTableView to handle pagination you need to set:

multiSelectionTableView.supportsPagination = true

and you can add a target action to the control.

multiSelectionTableView.addTarget(self, action: #selector(loadMoreData(sender:)), for: .scrollReachingEnd)

Aditionally, you can have some control of when to get more data setting

multiSelectionTableView.paginationNotificationRowIndex = 5

this will call .scrollReachingEnd action 5 rows before reaching the end of the table, so you can pre fetch next page data.

Empty State View

It’s common for results to come from the web, take some time loading, and/or be empty, and/or display an error. MultiSelectionTable has got you covered. If you want to display a custom empty view, just set the stateView with your view. For example a loading indicator:

let loadingView = UIActivityIndicatorView(
loadingView.transform = CGAffineTransform.init(scaleX: 2, y: 2)
multiSelectionTableView.stateView = loadingView

Target Actions

swift … multiSelectionTableView.addTarget(self, action: #selector(selectedItem(sender:)), for: .itemSelected) multiSelectionTableView.addTarget(self, action: #selector(unselectedItem(sender:)), for: .itemUnselected)

//only called if supportsPagination is set to true multiSelectionTableView.addTarget(self, action: #selector(loadMoreData(sender:)), for: .scrollReachingEnd) …

@objc private func selectedItem(sender: MultiSelectionTableView) { print(“selected item”) }

@objc private func unselectedItem(sender: MultiSelectionTableView) { print(“unselected item”) } …

## Requirements

- iOS 9.0+
- Xcode 8.0+

## Installation


MultiSelectionTable is available through [CocoaPods]( To install
it, simply add the following line to your Podfile:

platform :ios, '9.0'

pod 'MultiSelectionTable', git: ''

(Currently MultiSelectionTable is still not yet published to Cocoapods, so for now you need to add swift git: ''.


Copy the contents of [Source]( folder into your project and you’re ready to go.


Missing features and/or bugs can be found in the Issues section.


Nuno Gonçalves

nunogoncalves @goncalvescmnuno


Feel free to contribute to MultiSelectionTable. Check Issues before asking something or adding some contribuition that’s already being done.


iOS-MultiSelectionTable is available under the MIT license. See the LICENSE file for more info.

Final note

If you use MultiSelectionTable in a production app, let me know. I’ll be very flattered and pleased and sure want to be aware of it. ?


View Github