A pixel perfect replacement for UITableView section index written in Swift

MYTableViewIndex

MYTableViewIndex is a re-implementation of UITableView section index. This control is usually seen in apps displaying contacts, tracks, and other alphabetically sorted data. MYTableViewIndex completely replicates native iOS section index, but can also display images and has additional customization capabilities.

Features

  • Can display images
  • Fully customizable: use custom fonts, background views, add your own type of items
  • Compatible with any UIScrollView subclass
  • Works properly with UITableViewController and UICollectionViewController
  • Automatic layout, inset management and keyboard avoidance (via TableViewIndexController)
  • Right-to-left languages support
  • Haptic Feedback support
  • Accessibility support

Below are the screenshots for some of the features:

Usage

1. Instantiation

Manual setup

The component is a UIControl subclass and can be used as any other view, simply by adding it to the view hierarchy. This can be done via Interface Builder or in code:

let tableViewIndex = tableViewIndex(frame: CGRect())
view.addSubview(tableViewIndex)

Note that in this case no layout is done automatically and all the required index view alignment is completely up to you.

Using TableViewIndexController

Things get more complicated when dealing with UITableViewController/UICollectionViewController. The root view of these view controllers is a UIScrollView descendant and using it as a superview for TableViewIndex is generally a bad idea, since UIScrollView delays touch delivery by default.

Enter TableViewIndexController. When used, it creates a TableViewIndex instance, adds it to the hierarchy as a sibling of the root view and sets up the layout. The controller also observes UIScrollView insets and updates index view size accordingly. This makes sense when the keyboard shows up, for example.

You can also use the controller to hide TableViewIndex for certain table sections like Apple once did in its Music app:

Using TableViewIndexController the setup can be done in just one line of code:

let tableViewIndexController = TableViewIndexController(scrollView: tableView)

2. Data source

To feed index view with data, one should simply implement the following method of TableViewIndexDataSource protocol:

func indexItems(for tableViewIndex: TableViewIndex) -> [UIView] {
    return UILocalizedIndexedCollation.currentCollation().sectionIndexTitles.map{ title -> UIView in
        return StringItem(text: title)
    }
}

And attach it to the index view:

tableViewIndexController.tableViewIndex.dataSource = dataSourceObject

Several predefined types of items are available for displaying strings, images, magnifying glass, and truncation symbols. You can provide your own type of item though.

3. Delegate

To respond to index view touches and scroll table to the selected section, one should provide a delegate object and implement the following method:

func tableViewIndex(_ tableViewIndex: TableViewIndex, didSelect item: UIView, at index: Int) -> Bool {
    let indexPath = NSIndexPath(forRow: 0, inSection: sectionIndex)
    tableView.scrollToRowAtIndexPath(indexPath, atScrollPosition: .Top, animated: false)
    
    return true // return true to produce haptic feedback on capable devices 
}

4. Customization

MYTableViewIndex is fully customizable. See TableViewIndex properties for more details.

Example

To run the example project, clone the repo, and run pod install from the Example directory first.

Requirements

  • iOS 8.0+
  • Swift 5.0

Installation

CocoaPods

MYTableViewIndex is available through CocoaPods. To install
it, simply add the following line to your Podfile:

pod 'MYTableViewIndex'

Manually

Download and drop all .swift files from MYTableViewIndex folder to your project.

Objective-C

All public classes of MYTableViewIndex are exposed to Objective-C, just import the library module:

@import MYTableViewIndex;

And don't forget to enable frameworks in your Podfile:

use_frameworks!

Author

Makarov Yuriy, makarov.yuriy@gmail.com

GitHub