|
|
|
import UIKit |
|
|
|
|
|
// MARK: - Notifications |
|
|
|
extension Notification.Name { |
|
|
|
/// Posted everytime when a `SharedOffsetCollectionView` scrolls. The object is the instances that got scrolled. |
|
fileprivate static let didScroll = Notification.Name(rawValue: "SharedContentOffset.didScroll") |
|
} |
|
|
|
// MARK: - Class Definition |
|
|
|
/// `UICollectionView` subclass that makes all its instances have the same scroll offset. |
|
/// When one instance scrolls all others will follow to the same content offset. |
|
class SharedOffsetCollectionView: UICollectionView { |
|
|
|
/// Simple flag used for internal logic control. |
|
private var shouldTrack = true |
|
|
|
override var contentOffset: CGPoint { |
|
willSet { |
|
NotificationCenter.default.removeObserver(self, name: .didScroll, object: nil) |
|
NotificationCenter.default.addObserver(self, selector: #selector(scrollOccured(_:)), name: .didScroll, object: nil) |
|
} |
|
didSet { |
|
guard shouldTrack == true else { return } |
|
NotificationCenter.default.post(name: .didScroll, object: self) |
|
} |
|
} |
|
|
|
deinit { |
|
NotificationCenter.default.removeObserver(self, name: .didScroll, object: nil) |
|
} |
|
} |
|
|
|
// MARK: - Notifications |
|
|
|
extension SharedOffsetCollectionView { |
|
|
|
/// Called when a `SharedOffsetCollectionView` scrolls. |
|
/// It sets the content offset of other instances to the one that got scrolled |
|
/// while making them not track that change to avoid recursion. |
|
@objc private func scrollOccured(_ notification: Notification) { |
|
guard let scrollView = notification.object as? UIScrollView else { return } |
|
guard scrollView != self else { return } |
|
|
|
shouldTrack = false |
|
setContentOffset(scrollView.contentOffset, animated: false) |
|
shouldTrack = true |
|
} |
|
} |
If you want collection views to scroll simultaneously, make them subclass from this class and they will. You can apply the same technique to tableviews and scroll views as well, by just changing the parent class from
UICollectionViewto eitherUIScrollVieworUITableView