Question

I was wondering if there is any way to get a more accurate version of the contentOffset, or estimate/calculate the contentOffset or (preferably) the first derivative of contentOffset of a UIScrollView. I am trying to perform an action when the rate of change of the contentOffset of my UIScrollView is very small, but 0.5f isn't quite precise enough.

Any help is greatly appreciated.

Was it helpful?

Solution

You can't get better precision than the one provided by contentOffset. You could calculate velocity using regular ds/dt equation:

- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
    static CGFloat prevPos = 0.0; //you can store those in iVars
    static NSTimeInterval prevTime = 0.0;

    CGFloat newPos = scrollView.contentOffset.y;
    NSTimeInterval newTime = [NSDate timeIntervalSinceReferenceDate];

    double v = (newPos - prevPos)/(newTime - prevTime);

    prevPos = newPos;
    prevTime = newTime;
}

However, if you are feeling extremely hacky, and you want you code to be unsafe, you can peek into UIScrollView's velocity iVars directly by using this category

@interface UIScrollView(UnsafeVelocity)
- (double) unsafeVerticalVelocty;
@end

@implementation UIScrollView(UnsafeVelocity)

- (double) unsafeVerticalVelocty
{
    double returnValue = 0.0;
    id verticalVel = nil;

    @try {
        verticalVel = [self valueForKey:@"_verticalVelocity"];
    }
    @catch (NSException *exception) {
        NSLog(@"KVC peek failed!");
    }
    @finally {
        if ([verticalVel isKindOfClass:[NSNumber class]]) {
            returnValue = [verticalVel doubleValue];
        }
    }

    return returnValue;
}

@end

To get horizontal velocity replace _verticalVelocity with _horizontalVelocity. Notice, that the values you will get seem to be scaled differently. I repeat once more: while this is (probably) the best value of velocity you can get, it is very fragile and not future-proof.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top