Skip to content

Instantly share code, notes, and snippets.

@shaps80
Last active July 10, 2018 19:34
Show Gist options
  • Select an option

  • Save shaps80/31357a6dca9f627c22c94ec78dc63197 to your computer and use it in GitHub Desktop.

Select an option

Save shaps80/31357a6dca9f627c22c94ec78dc63197 to your computer and use it in GitHub Desktop.
//
// IndexPathSelection.swift
// Credit: https://www.raizlabs.com/dev/2016/05/smarter-animated-row-deselection-ios/
//
// This version by Shahpour Benkau on 21/05/2017 – based on the version from raizlabs.com
//
import UIKit
// Represents a view that provides indexPath selection (e.g. UITableView, UICollectionView)
public protocol IndexPathSelectionProviding {
var selectedIndexPaths: [IndexPath] { get }
func deselect(indexPath: IndexPath, animated: Bool)
func select(indexPath: IndexPath, animated: Bool)
}
extension UITableView: IndexPathSelectionProviding {
public var selectedIndexPaths: [IndexPath] {
return indexPathsForSelectedRows ?? []
}
public func select(indexPath: IndexPath, animated: Bool) {
selectRow(at: indexPath, animated: animated, scrollPosition: .none)
}
public func deselect(indexPath: IndexPath, animated: Bool) {
deselectRow(at: indexPath, animated: animated)
}
}
extension UICollectionView: IndexPathSelectionProviding {
public var selectedIndexPaths: [IndexPath] {
return indexPathsForSelectedItems ?? []
}
public func select(indexPath: IndexPath, animated: Bool) {
selectItem(at: indexPath, animated: animated, scrollPosition: [])
}
public func deselect(indexPath: IndexPath, animated: Bool) {
deselectItem(at: indexPath, animated: animated)
}
}
// Represents a view that hosts an indexPath selection provider.
protocol IndexPathSelectionHosting {
var indexPathSelectionProvider: IndexPathSelectionProviding? { get }
var transitionCoordinator: UIViewControllerTransitionCoordinator? { get }
}
extension UITableViewController: IndexPathSelectionHosting {
var indexPathSelectionProvider: IndexPathSelectionProviding? {
return tableView
}
}
extension UICollectionViewController: IndexPathSelectionHosting {
var indexPathSelectionProvider: IndexPathSelectionProviding? {
return collectionView
}
}
/**
Provides the default implementation for clearing the selection during an interactive gesture.
This also handles cancelled interactions.
Usage:
func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated: animated)
clearSelection()
}
If you're using something other than a UITableViewController or UICollectionViewController, you can opt-in to this same protocol as such:
extension MyViewController: IndexPathSelectionHosting { }
*/
extension IndexPathSelectionHosting {
public func clearSelection() {
guard let indexPaths = indexPathSelectionProvider?.selectedIndexPaths else { return }
// Grab the transition coordinator responsible for the current transition
if let coordinator = transitionCoordinator {
coordinator.animate(alongsideTransition: { context in
// Deselect the cells, with animations enabled if this is an animated transition
indexPaths.forEach {
self.indexPathSelectionProvider?.deselect(indexPath: $0, animated: context.isAnimated)
}
}, completion: { context in
// If the transition was cancel, reselect the rows that were selected before,
// so they are still selected the next time the same animation is triggered
if context.isCancelled {
indexPaths.forEach {
self.indexPathSelectionProvider?.select(indexPath: $0, animated: false)
}
}
})
}
else { // If this isn't a transition coordinator, just deselect the rows without animating
indexPathSelectionProvider?.selectedIndexPaths.forEach {
indexPathSelectionProvider?.deselect(indexPath: $0, animated: false)
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment