Skip to content

Commit

Permalink
Merge pull request #29 from NicFontana/fix/rows-visibility-changes-de…
Browse files Browse the repository at this point in the history
…legate-calls

Fix: `ScrollStackControllerDelegate` methods calls
  • Loading branch information
malcommac authored May 20, 2024
2 parents d07064e + 6213415 commit da3787b
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 21 deletions.
57 changes: 38 additions & 19 deletions Sources/ScrollStackController/ScrollStack.swift
Original file line number Diff line number Diff line change
Expand Up @@ -860,6 +860,8 @@ open class ScrollStack: UIScrollView, UIScrollViewDelegate {
return createRow(newRow, at: index, cellToRemove: cellToRemove, animated: animated, completion: completion)
}

private var rowVisibilityChangesDispatchWorkItem: DispatchWorkItem?

/// Private implementation to add new row.
private func createRow(_ newRow: ScrollStackRow, at index: Int,
cellToRemove: ScrollStackRow?,
Expand All @@ -878,7 +880,21 @@ open class ScrollStack: UIScrollView, UIScrollViewDelegate {
}, completion: nil)
}

scrollViewDidScroll(self)
if rowVisibilityChangesDispatchWorkItem == nil {

rowVisibilityChangesDispatchWorkItem = DispatchWorkItem(block: { [weak self] in
if let stackDelegate = self?.stackDelegate {
self?.dispatchRowsVisibilityChangesTo(stackDelegate)
}

self?.rowVisibilityChangesDispatchWorkItem = nil
})

/// Schedule a single `dispatchRowsVisibilityChangesTo(_:)` call.
///
/// In this way, when rows are created inside a for-loop, the delegate is called only once after the `ScrollStack` has been fully laid out.
DispatchQueue.main.async(execute: rowVisibilityChangesDispatchWorkItem!)
}

return newRow
}
Expand Down Expand Up @@ -979,25 +995,27 @@ open class ScrollStack: UIScrollView, UIScrollViewDelegate {
}

private func dispatchRowsVisibilityChangesTo(_ delegate: ScrollStackControllerDelegate) {
delegate.scrollStackDidScroll(self, offset: contentOffset)

rows.enumerated().forEach { (idx, row) in
let current = isRowVisible(index: idx)
if let previous = prevVisibilityState[row] {
switch (previous, current) {
case (.offscreen, .partial), // row will become invisible
(.hidden, .partial),
(.hidden, .entire):
delegate.scrollStackRowDidBecomeVisible(self, row: row, index: idx, state: current)

case (.partial, .offscreen), // row will become visible
(.partial, .hidden),
(.entire, .hidden):
delegate.scrollStackRowDidBecomeHidden(self, row: row, index: idx, state: current)

default:
break
}
let previous = prevVisibilityState[row]

switch (previous, current) {
case (.offscreen, .partial), // row will become visible
(nil, .entire),
(nil, .partial),
(.partial, .entire),
(.hidden, .partial),
(.hidden, .entire):
delegate.scrollStackRowDidBecomeVisible(self, row: row, index: idx, state: current)

case (.partial, .offscreen), // row will become invisible
(.entire, .partial),
(.partial, .hidden),
(.entire, .hidden):
delegate.scrollStackRowDidBecomeHidden(self, row: row, index: idx, state: current)

default:
break
}

// store previous state
Expand Down Expand Up @@ -1062,7 +1080,8 @@ open class ScrollStack: UIScrollView, UIScrollViewDelegate {
guard let stackDelegate = stackDelegate else {
return
}

stackDelegate.scrollStackDidScroll(self, offset: contentOffset)

dispatchRowsVisibilityChangesTo(stackDelegate)
}

Expand Down
5 changes: 3 additions & 2 deletions Sources/ScrollStackController/ScrollStackRow.swift
Original file line number Diff line number Diff line change
Expand Up @@ -239,10 +239,11 @@ open class ScrollStackRow: UIView, UIGestureRecognizerDelegate {
setNeedsUpdateConstraints()
}

open override func layoutSubviews() {
super.layoutSubviews()
open override func updateConstraints() {
// called the event to update the height of the row.
askForCutomizedSizeOfContentView(animated: false)

super.updateConstraints()
}

private func applyParentStackAttributes() {
Expand Down

0 comments on commit da3787b

Please sign in to comment.