Created
May 20, 2020 17:23
-
-
Save nitin-agam/45b8a8735eb3c5feb2d0f03e52a00673 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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