Search code examples
iosswiftuiscrollviewswift4uicontrol

UIScrollView as UIControl


I am implementing a UIControl using UIScrollView. I wish to send .valueChanged event when user scrolls the scroll view with finger, not otherwise. To do this, I need to compare the currentValue I compute when the scrolling happens, and if it is different than previous value, I send a .valueChanged event via sendActionsForControlEvents API. My questions:

(a) What is the most reliable way in all cases to know that user dragged the scroll view(scrolling can also happen in my code using automated API) -- scrollView.isDragging or scrollView.isTracking, or both?

(b) What is the way to notice change in currentValue (without storing previous value)? I am doing this using Swift 4 but it doesn't seems to give old value:

 private(set) public var currentValue = Int(0) {
    willSet (newValue) {
        NSLog("Old value \(currentValue), new \(newValue)")
    }
 }

Solution

  • From the comments using delegates I believe the solid solution should look something similar to:

    class MyClass: NSObject, UIScrollViewDelegate {
    
        private var isUserDragging: Bool = false
    
        func scrollViewDidScroll(_ scrollView: UIScrollView) {
            if isUserDragging {
                // Should trigger only when scroll view visible frame changes and user is dragging
                print("User is dragging")
            }
        }
    
        func scrollViewWillBeginDragging(_ scrollView: UIScrollView) {
            isUserDragging = true // Should only be called when user starts dragging
        }
    
        func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) {
            if decelerate == false {
                isUserDragging = false // Disable user dragging only if no deceleration will be performed
            }
        }
    
        func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
            isUserDragging = false // When deceleration is done user is not dragging anymore
        }
    
    }
    

    Now you should be able to get your event within scrollViewDidScroll.