Skip to content

Instantly share code, notes, and snippets.

@stoqn4opm
Created May 21, 2020 05:57
Show Gist options
  • Save stoqn4opm/6d2f8bc765a515a5cc3d81e4a4cbceab to your computer and use it in GitHub Desktop.
Save stoqn4opm/6d2f8bc765a515a5cc3d81e4a4cbceab to your computer and use it in GitHub Desktop.
`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.
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
}
}
@stoqn4opm
Copy link
Author

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 UICollectionView to either UIScrollView or UITableView

@J-Arji
Copy link

J-Arji commented Sep 2, 2020

great
Can you give an example of its use?

@stoqn4opm
Copy link
Author

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment