In Swift, how would you write the scrollViewWillEndDragging withVelocity targetContentOffset method?

11,730

Solution 1

To answer from Christian: I was able to rewrite this in Swift. I set everything up as Float to do the math then converted to CGFloat as Christian mentioned was possible. His answer is technically correct, but showing a newer iOS developer how this is written in Swift was what I was looking for.

func scrollViewWillEndDragging(scrollView: UIScrollView!, withVelocity velocity: CGPoint, targetContentOffset: UnsafePointer<CGPoint>) {

     var pageWidth = Float(200 + 30)
     var currentOffset = Float(scrollView.contentOffset.x)
     var targetOffset = Float(targetContentOffset.memory.x)
     var newTargetOffset = Float(0)
     var scrollViewWidth = Float(scrollView.contentSize.width)

     if targetOffset > currentOffset {
         newTargetOffset = ceilf(currentOffset / pageWidth) * pageWidth
     } else {
         newTargetOffset = floorf(currentOffset / pageWidth) * pageWidth
     }

     if newTargetOffset < 0 {
         newTargetOffset = 0
     } else if newTargetOffset > currentOffset {
         newTargetOffset = currentOffset
     }

     Float(targetContentOffset.memory.x) == currentOffset

     scrollView.setContentOffset(CGPointMake(CGFloat(newTargetOffset), 0), animated: true)
 }

Solution 2

Maybe later for the party, but none of the proposed solutions are viable solution if dealing with iOS11 + Swift4, IMHO.

Below there is a more suitable answer for the problem, fully working with Swift 4.1:

override func scrollViewWillEndDragging(_ scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint>) {

    let pageWidht:CGFloat = 200.0 + 30.0
    let currentOffset = scrollView.contentOffset.x
    let targetOffset = CGFloat(targetContentOffset.pointee.x)
    var newTargetOffset:CGFloat = 0.0

    if targetOffset > currentOffset {
        newTargetOffset = CGFloat(ceilf(Float((currentOffset / pageWidht) * pageWidht)))
    }
    else {
        newTargetOffset = CGFloat(floorf(Float((currentOffset / pageWidht) * pageWidht)))
    }

    if newTargetOffset < 0.0 {
        newTargetOffset = 0.0
    }
    else if newTargetOffset > scrollView.contentSize.width {
        newTargetOffset = scrollView.contentSize.width
    }
    targetContentOffset.pointee = CGPoint(x: newTargetOffset, y: 0.0)
}

Solution 3

You can use ceil or floor. Apple now allows CGFloat as parameter in common functions like these. For example:

func ceil(x: CGFloat) -> CGFloat

So in your example:

ceil(currentOffset/pageWidth)

Solution 4

well, that's not work for me, and i get a compromise method, use the scrollViewDidEndDecelerating

    var targetOffSet:CGPoint?
    func scrollViewWillEndDragging(scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint>) {
        var offsetX:CGFloat = targetContentOffset.memory.x
        offsetX -= someValue
        self.targetOffSet = CGPoint(x: offsetX, y: 0)
}
func scrollViewDidEndDecelerating(scrollView: UIScrollView) {
    if self.targetOffSet != nil {
        scrollView.setContentOffset(self.targetOffSet!, animated: true)
        self.targetOffSet = nil
    }
}
Share:
11,730
Aubrey
Author by

Aubrey

Software Designer. Husband. Dad of 2. Now DIR at Science Prev Twilio &amp; Color http://github.com/aubrey http://dribbble.com/aubrey

Updated on June 22, 2022

Comments

  • Aubrey
    Aubrey almost 2 years

    How would one write this in Swift?

    Update: posted the method I'm trying to convert, originally posted a different method that was not what I was trying to covert

    This works in Objective C, but not Swift. I get conversion errors when I try to use ceilf and floorf with CGFloat.

        - (void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)targetContentOffset
    {
    
        float pageWidth = 200 + 30; // width + space
    
        float currentOffset = scrollView.contentOffset.x;
        float targetOffset = targetContentOffset->x;
        float newTargetOffset = 0;
    
        if (targetOffset > currentOffset)
            newTargetOffset = ceilf(currentOffset / pageWidth) * pageWidth;
        else
            newTargetOffset = floorf(currentOffset / pageWidth) * pageWidth;
    
        if (newTargetOffset < 0)
            newTargetOffset = 0;
        else if (newTargetOffset > scrollView.contentSize.width)
            newTargetOffset = scrollView.contentSize.width;
    
        targetContentOffset->x = currentOffset;
        [scrollView setContentOffset:CGPointMake(newTargetOffset, 0) animated:YES];
    
    
    }