1

In my collectionView the cells are the size of the entire screen, I use vertical scrolling, and I have .isPagingEnabled = true. I needed to prevent the user from swiping fast. Changing the .decelerationRate didn't work. The only thing that I found was to disable/enable the scrollView as the user swipes which almost works fine.

In the pic below, when the swiping starts, I disable the scrollView and show a red label at the top that says "cv Disabled". When swiping ends because the user lifted their finger, I enable the scrollView and remove the label. But when I swipe a hairline bit and quickly lift my finger from the cell, the red label never disappears and the scroll stays disabled. The orange arrow points to the next cell with a beige background that's about to be shown when I subtly swiped.

enter image description here

In the code below using both tries everything works fine when scrolling past a certain point occurs like full screen or a quarter of the screen. The issue is if I subtly swipe a hairline bit, the scrollView stays disabled because the methods myScrollView?.isUserInteractionEnabled = true are in never gets fired.

1st try:

var myScrollView: UIScrollView?

func scrollViewWillBeginDragging(_ scrollView: UIScrollView) {

    if myScrollView == nil {
        myScrollView = scrollView
    }

    myScrollView?.isUserInteractionEnabled = false

    showRedDisabledLabel()
}

func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {

    myScrollView?.isUserInteractionEnabled = true

    removeRedDisabledLabel()
}

2nd try:

func scrollViewWillBeginDragging(_ scrollView: UIScrollView) {

    if myScrollView == nil {
        myScrollView = scrollView
    }

    myScrollView?.isUserInteractionEnabled = false

    showRedDisabledLabel()
}

func scrollViewDidScroll(_ scrollView: UIScrollView) {

    NSObject.cancelPreviousPerformRequests(withTarget: self)
    perform(#selector(UIScrollViewDelegate.scrollViewDidEndScrollingAnimation), with: nil, afterDelay: 0.3)
}

func scrollViewDidEndScrollingAnimation(_ scrollView: UIScrollView) {

    myScrollView?.isUserInteractionEnabled = true

    removeRedDisabledLabel()

    NSObject.cancelPreviousPerformRequests(withTarget: self)
}

This problem literally only occurs when I swipe that hairline bit and quickly lift my finger, every other time the code from both tries works perfectly. The question is in scrollViewWillBeginDragging, how can I detect when a user swipes past a certain point so that I can then set myScrollView?.isUserInteractionEnabled = false

Lance Samaria
  • 17,576
  • 18
  • 108
  • 256

1 Answers1

0

I couldn't find a way to to determine how much a user swiped in scrollViewWillBeginDragging but I did find a workaround to the actual problem of hairline scrolling. I put myScrollView?.isUserInteractionEnabled and the redLabel into their own functions, combined this answer and this answer, created an instance property named isScrolling, and use didSet to determine if it's scrolling or not and call the functions from there:

// Properties
var myScrollView: UIScrollView?

var isScrolling = false {
    didSet {

        if isScrolling {

            disableScrollView()

        } else {

            enableScrollView()
        }
    }
}

// My 2 Functions
func disableScrollView() {
    myScrollView?.isUserInteractionEnabled = false
    showRedDisabledLabel()
}

func enableScrollView() {
    myScrollView?.isUserInteractionEnabled = true
    removeRedDisabledLabel()
}

// UIScrollView Delegate Methods
func scrollViewWillBeginDragging(_ scrollView: UIScrollView) {
    
    if myScrollView == nil {
        myScrollView = scrollView
    }
    
    isScrolling = true
}

func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) {
    
    if !decelerate {
        isScrolling = false
    }
}

func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
    
    isScrolling = false
}

func scrollViewDidScroll(_ scrollView: UIScrollView) {

    NSObject.cancelPreviousPerformRequests(withTarget: self)
    perform(#selector(UIScrollViewDelegate.scrollViewDidEndScrollingAnimation), with: nil, afterDelay: 0.3)
}

func scrollViewDidEndScrollingAnimation(_ scrollView: UIScrollView) {

    isScrolling = false
    NSObject.cancelPreviousPerformRequests(withTarget: self)
}
Lance Samaria
  • 17,576
  • 18
  • 108
  • 256