Skip to content

Instantly share code, notes, and snippets.

@ohyeh
Last active April 25, 2022 16:08
Show Gist options
  • Save ohyeh/95ee2f961a9eb65c6225e189ac5710f3 to your computer and use it in GitHub Desktop.
Save ohyeh/95ee2f961a9eb65c6225e189ac5710f3 to your computer and use it in GitHub Desktop.
//
// ScrollViewObserver.swift
// IndoChat
//
// Copyright © 2022 PT. ICE Messenger Indonesia. All rights reserved.
//
import UIKit
// https://stackoverflow.com/questions/26953559/in-swift-how-do-i-have-a-uiscrollview-subclass-that-has-an-internal-and-externa
class ScrollViewObserver: NSObject {
// MARK: - Private Properties
weak var proxyDelegate: UIScrollViewDelegate?
fileprivate(set) weak var scrollView: UIScrollView?
fileprivate(set) weak var originalScrollDelegate: UIScrollViewDelegate?
fileprivate var primaryScrollViewDelegate: UIScrollViewDelegate? {
guard let proxyDelegate = self.proxyDelegate else {
return self.originalScrollDelegate
}
return proxyDelegate
}
// MARK: - Instantiation
init(scrollView: UIScrollView) {
super.init()
self.scrollView = scrollView
self.originalScrollDelegate = scrollView.delegate
scrollView.delegate = self
}
deinit {
printLog("")
self.remove()
}
func remove() {
self.proxyDelegate = nil
self.scrollView?.delegate = self.originalScrollDelegate
}
override func responds(to aSelector: Selector!) -> Bool {
return self.proxyDelegate?.responds(to: aSelector) == true || self.originalScrollDelegate?.responds(to:aSelector) == true || super.responds(to: aSelector)
}
override func forwardingTarget(for aSelector: Selector!) -> Any? {
if let rawObject = self.proxyDelegate, rawObject.responds(to: aSelector) {
return rawObject
}
else if let defualtObject = self.originalScrollDelegate, defualtObject.responds(to: aSelector) {
return self.originalScrollDelegate
}
return super.forwardingTarget(for: aSelector)
}
}
// MARK: - Forwarding Delegates
/// Note: we forward all delegate calls here since Swift does not support forwardInvocation: or NSProxy
extension ScrollViewObserver: UIScrollViewDelegate {
func scrollViewDidScroll(_ scrollView: UIScrollView) {
self.primaryScrollViewDelegate?.scrollViewDidScroll?(scrollView)
}
func scrollViewDidZoom(_ scrollView: UIScrollView) {
self.primaryScrollViewDelegate?.scrollViewDidZoom?(scrollView)
}
func scrollViewWillBeginDragging(_ scrollView: UIScrollView) {
self.primaryScrollViewDelegate?.scrollViewWillBeginDragging?(scrollView)
}
func scrollViewWillEndDragging(_ scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint>) {
self.primaryScrollViewDelegate?.scrollViewWillEndDragging?(scrollView, withVelocity: velocity, targetContentOffset: targetContentOffset)
}
func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) {
self.primaryScrollViewDelegate?.scrollViewDidEndDragging?(scrollView, willDecelerate: decelerate)
}
func scrollViewWillBeginDecelerating(_ scrollView: UIScrollView) {
self.primaryScrollViewDelegate?.scrollViewWillBeginDecelerating?(scrollView)
}
func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
self.primaryScrollViewDelegate?.scrollViewDidEndDecelerating?(scrollView)
}
func scrollViewDidEndScrollingAnimation(_ scrollView: UIScrollView) {
self.primaryScrollViewDelegate?.scrollViewDidEndScrollingAnimation?(scrollView)
}
func viewForZooming(in scrollView: UIScrollView) -> UIView? {
return self.primaryScrollViewDelegate?.viewForZooming?(in: scrollView)
}
func scrollViewWillBeginZooming(_ scrollView: UIScrollView, with view: UIView?) {
self.primaryScrollViewDelegate?.scrollViewWillBeginZooming?(scrollView, with: view)
}
func scrollViewDidEndZooming(_ scrollView: UIScrollView, with view: UIView?, atScale scale: CGFloat) {
self.primaryScrollViewDelegate?.scrollViewDidEndZooming?(scrollView, with: view, atScale: scale)
}
func scrollViewShouldScrollToTop(_ scrollView: UIScrollView) -> Bool {
return self.primaryScrollViewDelegate?.scrollViewShouldScrollToTop?(scrollView) == true
}
func scrollViewDidScrollToTop(_ scrollView: UIScrollView) {
self.primaryScrollViewDelegate?.scrollViewDidScrollToTop?(scrollView)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment