Skip to content

Instantly share code, notes, and snippets.

@nitin-agam
Created May 20, 2020 17:23
Show Gist options
  • Save nitin-agam/45b8a8735eb3c5feb2d0f03e52a00673 to your computer and use it in GitHub Desktop.
Save nitin-agam/45b8a8735eb3c5feb2d0f03e52a00673 to your computer and use it in GitHub Desktop.
import UIKit
// MARK: - IndexPaths
extension UICollectionView {
var lastIndexPath: IndexPath? {
return lastIndexPath(inSection: lastSection)
}
var lastSection: Int {
return numberOfSections > 0 ? numberOfSections - 1 : 0
}
func numberOfItems() -> Int {
var section = 0
var itemsCount = 0
while section < numberOfSections {
itemsCount += numberOfItems(inSection: section)
section += 1
}
return itemsCount
}
func lastIndexPath(inSection section: Int) -> IndexPath? {
guard section >= 0 else {
return nil
}
guard section < numberOfSections else {
return nil
}
guard numberOfItems(inSection: section) > 0 else {
return IndexPath(item: 0, section: section)
}
return IndexPath(item: numberOfItems(inSection: section) - 1, section: section)
}
}
// MARK: - Registeration
extension UICollectionView {
func register<T: UICollectionReusableView>(supplementaryView kind: String, className: T.Type) {
register(T.self, forSupplementaryViewOfKind: kind, withReuseIdentifier: String(describing: className))
}
func registerHeader<T: UICollectionReusableView>(supplementaryView className: T.Type) {
register(T.self, forSupplementaryViewOfKind: UICollectionView.elementKindSectionHeader,
withReuseIdentifier: String(describing: className))
}
func registerFooter<T: UICollectionReusableView>(supplementaryView className: T.Type) {
register(T.self, forSupplementaryViewOfKind: UICollectionView.elementKindSectionFooter,
withReuseIdentifier: String(describing: className))
}
func register<T: UICollectionViewCell>(_ classType: T.Type) {
register(T.self, forCellWithReuseIdentifier: String(describing: classType))
}
}
// MARK: - Dequeuing
extension UICollectionView {
func dequeueCell<T: UICollectionViewCell>(withClass name: T.Type, for indexPath: IndexPath) -> T {
guard let cell = dequeueReusableCell(withReuseIdentifier: String(describing: name),
for: indexPath) as? T else {
fatalError("Couldn't find UICollectionViewCell for \(String(describing: name)), make sure the cell is registered with collection view")
}
return cell
}
func dequeueHeader<T: UICollectionReusableView>(className: T.Type, for indexPath: IndexPath) -> T {
guard let cell = dequeueReusableSupplementaryView(ofKind: UICollectionView.elementKindSectionHeader, withReuseIdentifier: String(describing: className), for: indexPath) as? T else {
fatalError("Couldn't find header for \(String(describing: className)), make sure the view is registered with collection view")
}
return cell
}
func dequeueFooter<T: UICollectionReusableView>(className: T.Type, for indexPath: IndexPath) -> T {
guard let cell = dequeueReusableSupplementaryView(ofKind: UICollectionView.elementKindSectionFooter, withReuseIdentifier: String(describing: className), for: indexPath) as? T else {
fatalError("Couldn't find footer for \(String(describing: className)), make sure the view is registered with collection view")
}
return cell
}
}
// MARK: - Scrolling
extension UICollectionView {
func safeScrollToItem(indexPath: IndexPath,
position: UICollectionView.ScrollPosition,
animated: Bool) {
guard indexPath.item >= 0 &&
indexPath.section >= 0 &&
indexPath.section < numberOfSections &&
indexPath.item < numberOfItems(inSection: indexPath.section) else {
return
}
scrollToItem(at: indexPath, at: position, animated: animated)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment