Created
June 21, 2023 17:37
-
-
Save VaslD/e616d00609392a8d5c9da1513034046f 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 | |
open class UICollectionViewPlus: UICollectionView, UICollectionViewDelegate { | |
// MARK: Scroll | |
override public init(frame: CGRect, collectionViewLayout layout: UICollectionViewLayout) { | |
super.init(frame: frame, collectionViewLayout: layout) | |
super.delegate = self | |
} | |
public required init?(coder: NSCoder) { | |
super.init(coder: coder) | |
super.delegate = self | |
} | |
private var _delegate: UICollectionViewDelegate? | |
override open var delegate: UICollectionViewDelegate? { | |
get { self._delegate } | |
set { | |
self._delegate = newValue | |
super.delegate = self | |
} | |
} | |
override open func responds(to selector: Selector!) -> Bool { | |
self.responds(to: selector) || self._delegate?.responds(to: selector) == true | |
} | |
override open func forwardingTarget(for selector: Selector!) -> Any? { | |
self._delegate?.responds(to: selector) == true ? self._delegate : nil | |
} | |
private var scrollToItemCompletionHandler: ((UICollectionView, Bool) -> Void)? | |
open func scrollToItem(at indexPath: IndexPath, at scrollPosition: UICollectionView.ScrollPosition, animated: Bool, | |
completion: @escaping (UICollectionView, _ animated: Bool) -> Void) { | |
// Fast path: Non-visible items must be scrolled to. | |
if !self.indexPathsForVisibleItems.contains(indexPath) { | |
self.scrollToItemCompletionHandler = completion | |
self.scrollToItem(at: indexPath, at: scrollPosition, animated: true) | |
return | |
} | |
// Slow path: visible items may be scrolled to if not already in position. | |
let currentOffset = self.contentOffset | |
self.scrollToItem(at: indexPath, at: scrollPosition, animated: false) | |
let targetOffset = self.contentOffset | |
// Check if already in position. | |
if (currentOffset.x * 100).rounded() == (targetOffset.x * 100).rounded(), | |
(currentOffset.y * 100).rounded() == (targetOffset.y * 100).rounded() { | |
completion(self, false) | |
return | |
} | |
// Scroll will happen. Revert content offset and start animation. | |
self.contentOffset = currentOffset | |
self.scrollToItemCompletionHandler = completion | |
self.scrollToItem(at: indexPath, at: scrollPosition, animated: true) | |
} | |
public func scrollViewDidEndScrollingAnimation(_ scrollView: UIScrollView) { | |
self.scrollToItemCompletionHandler?(self, true) | |
self.scrollToItemCompletionHandler = nil | |
self._delegate?.scrollViewDidEndScrollingAnimation?(scrollView) | |
} | |
// MARK: Reload | |
open func reloadItems(at indexPaths: [IndexPath], | |
completion: @escaping (UICollectionView, _ animated: Bool) -> Void) { | |
self.performBatchUpdates { | |
self.reloadItems(at: indexPaths) | |
} completion: { | |
completion(self, $0) | |
} | |
} | |
open func reloadSections(_ sections: IndexSet, | |
completion: @escaping (UICollectionView, _ animated: Bool) -> Void) { | |
self.performBatchUpdates { | |
self.reloadSections(sections) | |
} completion: { | |
completion(self, $0) | |
} | |
} | |
private var reloadCompletionHandler: ((UICollectionView) -> Void)? | |
open func reloadData(completionHandler: @escaping (UICollectionView) -> Void) { | |
self.reloadCompletionHandler = completionHandler | |
self.reloadData() | |
} | |
override open func layoutSubviews() { | |
super.layoutSubviews() | |
self.reloadCompletionHandler?(self) | |
self.reloadCompletionHandler = nil | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment