Skip to content

Instantly share code, notes, and snippets.

@delannoyk
Created February 7, 2022 18:33
Show Gist options
  • Save delannoyk/e9bd6b2a8ff6706eb71056f2f8d87d60 to your computer and use it in GitHub Desktop.
Save delannoyk/e9bd6b2a8ff6706eb71056f2f8d87d60 to your computer and use it in GitHub Desktop.
import UIKit
private final class ScrollViewBehaviorContainer: NSObject, UIScrollViewDelegate {
// MARK: Properties
var behaviors = [ScrollViewBehavior]()
// MARK: UIScrollViewDelegate
func scrollViewDidScroll(_ scrollView: UIScrollView) {
behaviors.forEach { $0.afterScrolling(scrollView) }
}
func scrollViewDidZoom(_ scrollView: UIScrollView) {
behaviors.forEach { $0.afterZooming(scrollView) }
}
func scrollViewWillBeginDragging(_ scrollView: UIScrollView) {
behaviors.forEach { $0.beforeDraggingBegins(scrollView) }
}
func scrollViewWillEndDragging(_ scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint>) {
behaviors.forEach { $0.beforeDraggingEnds(scrollView, velocity: velocity, targetContentOffset: targetContentOffset) }
}
func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) {
behaviors.forEach { $0.afterDraggingEnds(scrollView, wilDecelerate: decelerate) }
}
func scrollViewWillBeginDecelerating(_ scrollView: UIScrollView) {
behaviors.forEach { $0.beforeDeceleratingBegins(scrollView) }
}
func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
behaviors.forEach { $0.afterDeceleratingEnds(scrollView) }
}
func scrollViewDidEndScrollingAnimation(_ scrollView: UIScrollView) {
behaviors.forEach { $0.afterScrollingAnimation(scrollView) }
}
func scrollViewWillBeginZooming(_ scrollView: UIScrollView, with view: UIView?) {
behaviors.forEach { $0.beforeZoomingBegins(scrollView, view: view) }
}
func scrollViewDidEndZooming(_ scrollView: UIScrollView, with view: UIView?, atScale scale: CGFloat) {
behaviors.forEach { $0.afterZoomingEnds(scrollView, view: view, scale: scale) }
}
func scrollViewDidScrollToTop(_ scrollView: UIScrollView) {
behaviors.forEach { $0.afterScrollingToTop(scrollView) }
}
func scrollViewDidChangeAdjustedContentInset(_ scrollView: UIScrollView) {
behaviors.forEach { $0.afterChangingAdjustedContentInset(scrollView) }
}
}
extension UIScrollView {
// MARK: Objective-C Runtime
private enum Keys {
static var behaviorContainer = "behaviorContainer"
}
private var behaviorContainer: ScrollViewBehaviorContainer {
if let container = objc_getAssociatedObject(self, &Keys.behaviorContainer) as? ScrollViewBehaviorContainer {
return container
}
let container = ScrollViewBehaviorContainer()
objc_setAssociatedObject(self, &Keys.behaviorContainer, container, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
return container
}
// MARK: Public methods
func addBehavior(_ behavior: ScrollViewBehavior) {
behaviorContainer.behaviors.append(behavior)
}
func addBehaviors(_ behaviors: [ScrollViewBehavior]) {
behaviorContainer.behaviors.append(contentsOf: behaviors)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment