9.5 C
New York
Tuesday, March 11, 2025

ios – Locking / Debouncing a scroll view Choice key statement in SwiftUI


I’ve a SwiftUI ScrollView for which I wish to carry out particular actions on scrolling and particularly when determining the scroll route.

That is my arrange to determine the scroll route:

ScrollView {
    content material
        .background(scrollDirectionTrackerView)
        .onPreferenceChange(ScrollOffsetKey.self) { updatedOffset in
            updateScrollDirection(updatedOffset)
        }
}
.coordinateSpace(title: "scrollView")

personal var scrollDirectionTrackerView: some View {
    GeometryReader { proxy in
        Colour.clear.desire(key: ScrollOffsetKey.self,
                               worth: -proxy.body(in: .named(coordinateSpaceKey)).origin.y)
    }
}

In case you see my code, I’ve the perform updateScrollDirection known as which is used to course of which route the consumer is scrolling in:

// Someplace throughout the View
personal let minimumDirectionChangeOffset = 16.0

personal var scrollDirectionUpdateHandler: ((ScrollDirection) -> Void)?

@State personal var currentDirection = ScrollDirection.none
@State personal var previousScrollOffset = CGFloat.zero

personal func updateScrollDirection(_ newOffset: CGFloat) {
    let offsetDifference = previousScrollOffset - newOffset
    var updatedDirection = currentDirection
    
    if abs(offsetDifference) > minimumDirectionChangeOffset {
        if offsetDifference > 0 {
            updatedDirection = axis == .vertical ? .up : .backward
        } else {
            updatedDirection = axis == .vertical ? .down : .ahead
        }
        
        previousScrollOffset = newOffset
    }

    // Solely publish if now we have a distinct route
    if updatedDirection != currentDirection {
        currentDirection = updatedDirection
        scrollDirectionUpdateHandler?(currentDirection) // The subscriber performs an animation 
    }
}

For essentially the most half this works properly. I wish to draw your consideration to the final line which is the place I write an animation occurs solely when the route adjustments.

If I carry out the scroll quick in both route, this works properly.

Nevertheless, once I drag actually slowly, I really feel both a race situation occurs with a number of threads accessing this perform or or one thing else, however the route will get set a number of instances triggering a number of animations which ends up in a uneven consumer expertise as a result of an animation being in progress.

I’m questioning if there’s a extra elegant strategy to deal with this:

  • with a debounce of some kinds
  • some form of semaphore / lock such that we will lock the perform
  • or higher math even ?

Another concepts that come to is a Bool variable to lock the perform however hoped for one thing extra elegant.

The animation to be carried out is the hiding / displaying of a UIKit based mostly View so the animation that occurs is a UIView.animate block that has a 0.5 period.

I attempted this outdated reply however it didn’t assist me.

Is there a greater strategy to stop the gradual drag from altering the scroll route a number of instances ?

Lastly, I have to assist iOS 16+.

Related Articles

LEAVE A REPLY

Please enter your comment!
Please enter your name here

Latest Articles