In Swift, how would you write the scrollViewWillEndDragging withVelocity targetContentOffset method?
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
}
}
Aubrey
Software Designer. Husband. Dad of 2. Now DIR at Science Prev Twilio & Color http://github.com/aubrey http://dribbble.com/aubrey
Updated on June 22, 2022Comments
-
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
andfloorf
withCGFloat
.- (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]; }