Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ internal class DefaultSimultaneouslyScrollViewHandler: NSObject, SimultaneouslyS
private var scrollViewsStore: [ScrollViewDecorator] = []
private weak var lastScrollingScrollView: UIScrollView?

private var cancellables: Set<AnyCancellable> = []
private let scrolledToBottomSubject = PassthroughSubject<Bool, Never>()

var scrolledToBottomPublisher: AnyPublisher<Bool, Never> {
Expand All @@ -21,36 +22,30 @@ internal class DefaultSimultaneouslyScrollViewHandler: NSObject, SimultaneouslyS
return
}

let currentDelegate: UIScrollViewDelegate? = scrollView.delegate

let multicastDelegate = {
if let multicastDelegate = scrollView.delegate as? MulticastScrollViewDelegate {
return multicastDelegate
} else {
let multicastDelegate = MulticastScrollViewDelegate()
if let currentDelegate {
multicastDelegate.addDelegate(currentDelegate)
}
scrollView.delegate = multicastDelegate
return multicastDelegate
}
}()

multicastDelegate.addDelegate(self)

scrollViewsStore.append(
ScrollViewDecorator(
scrollView: scrollView,
delegate: multicastDelegate,
handler: self,
directions: scrollDirections
)
)


scrollViewsStore.removeAll(where: {$0.scrollView == nil})

// Scroll the new `ScrollView` to the current position of the others.
// Using the first `ScrollView` should be enough as all should be synchronized at this point already.
guard let decorator = scrollViewsStore.first else {
return
}

scrollView.publisher(for: \.contentOffset)
.scan((old: scrollView.contentOffset, new: scrollView.contentOffset)) { (old: $0.new, new: $1) }
.sink { [weak self, weak scrollView] in
if let self, let scrollView {
self.handleContentOffsetChange(for: scrollView, oldValue: $0.old)
}
}
.store(in: &cancellables)

sync(scrollView: scrollView, with: decorator)

Expand Down Expand Up @@ -107,23 +102,30 @@ internal class DefaultSimultaneouslyScrollViewHandler: NSObject, SimultaneouslyS
registeredScrollView.setContentOffset(scrollView.contentOffset, animated: false)
}
}

var isUpdatingContentOffset: Bool = false
}

extension DefaultSimultaneouslyScrollViewHandler: UIScrollViewDelegate {
func scrollViewWillBeginDragging(_ scrollView: UIScrollView) {
lastScrollingScrollView = scrollView
}

func scrollViewDidScroll(_ scrollView: UIScrollView) {
func handleContentOffsetChange(for scrollView: UIScrollView, oldValue: CGPoint?) {
checkIsContentOffsetAtBottom()

guard lastScrollingScrollView == scrollView else {
guard oldValue != scrollView.contentOffset else {
return
}


guard !isUpdatingContentOffset else {
return
}

isUpdatingContentOffset = true
defer { isUpdatingContentOffset = false }

scrollViewsStore
.filter { $0.scrollView != lastScrollingScrollView }
.forEach { sync(scrollView: scrollView, with: $0) }
.filter { $0.scrollView != scrollView }
.forEach {
sync(scrollView: scrollView, with: $0)
}
}
}
#endif

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,16 @@ import UIKit

internal class ScrollViewDecorator {
weak var scrollView: UIScrollView?
var delegate: MulticastScrollViewDelegate
weak var handler: DefaultSimultaneouslyScrollViewHandler?
var directions: SimultaneouslyScrollViewDirection?

init(
scrollView: UIScrollView,
delegate: MulticastScrollViewDelegate,
handler: DefaultSimultaneouslyScrollViewHandler?,
directions: SimultaneouslyScrollViewDirection?
) {
self.scrollView = scrollView
self.delegate = delegate
self.handler = handler
self.directions = directions
}
}
Expand Down
43 changes: 0 additions & 43 deletions Sources/SimultaneouslyScrollView/Helper/WeakObjectStore.swift

This file was deleted.