【问题标题】:Find the movement speed of a UIView using a NSTimer or CADisplayLink使用 NSTimer 或 CADisplayLink 查找 UIView 的移动速度
【发布时间】:2014-04-28 08:13:57
【问题描述】:

我有一个滚动速度非常快的 UIScrollView,其中包含许多在重复使用时会更新的视图。

当滚动视图快速滚动时,我希望视图忽略他们可能需要做的任何新绘图(这需要从磁盘获取信息,例如图像等)

我考虑过创建一个 CADisplayLink(或者在本例中是一个 NSTimer)并计算在键窗口中更改的视图位置,就像这样

- (void)setupUpdateTimer
{
    self.shouldUpdateCoverPhoto = YES;
    self.previousFrame = CGRectNull;
    NSTimer *timer = [NSTimer timerWithTimeInterval:UpdateInterval target:self selector:@selector(timerUpdate:) userInfo:nil repeats:YES];
    [[NSRunLoop mainRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode];
    self.updateTimer = timer;

}

-(void)timerUpdate:(NSTimer *)timer
{
    CGRect currentFrame = [[UIApplication sharedApplication].keyWindow convertRect:self.frame fromView:self.superview];
    CGRect previousFrame = self.previousFrame;
    self.previousFrame = currentFrame;
    if (CGRectEqualToRect(previousFrame, CGRectNull))
    {
        self.shouldUpdateCoverPhoto = YES;
        return;
    }

    CGFloat distance = ABS(currentFrame.origin.y - previousFrame.origin.y);
    CGFloat speed = ABS(distance/UpdateInterval);
    DLog(@"Speed is %f",speed);
    if (speed < 1000)
    {

        self.shouldUpdateCoverPhoto = YES;
    } else {

        self.shouldUpdateCoverPhoto = NO;
    }
}

但是当视图快速改变位置时,不会定期调用计时器回调。

所以我不知道视图位置的定期变化是什么。

有没有更好的方法来做到这一点?

编辑

这是我想出的一个可能的解决方案(本着问题的精神),它可以实现非常快速的滚动(不一定在您可以访问代表的滚动视图中)。

- (void)setupUpdateTimer
{
    self.shouldUpdateCoverPhotoOnSlowLoop = NO;
    self.previousFrame = CGRectNull;
    self.scrollSpeed = 0;

    CADisplayLink *displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(checkNeedsUpdate:)];
    [displayLink addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSRunLoopCommonModes];
}

-(void)checkNeedsUpdate:(CADisplayLink *)link
{

    CGRect currentFrame = [[UIApplication sharedApplication].keyWindow convertRect:self.frame fromView:self.superview];
    CGRect previousFrame = self.previousFrame;
    self.previousFrame = currentFrame;
    if (CGRectEqualToRect(previousFrame, CGRectNull))
    {
        self.scrollSpeed = 0;
        return;
    }

    CGFloat distance = ABS(currentFrame.origin.y - previousFrame.origin.y);
    CGFloat duration = link.duration;
    CGFloat speed = ABS(distance/duration);


    self.scrollSpeed = speed;
    if (self.scrollSpeed < ThreasholdSpeedForCoverPhotoUpdate && self.shouldUpdateCoverPhotoOnSlowLoop)
    {
        [self setCoverPhotoForUser:_user];
    }

}

-(void)setCoverPhotoForUser:(id <InviGenericUserProtocol>)user
{
    if (self.scrollSpeed > ThreasholdSpeedForCoverPhotoUpdate && self.coverPhotoImageView.image != nil)
    {
        self.shouldUpdateCoverPhotoOnSlowLoop = YES;
        //DLog(@"Scroll speed %f greater than threashold %d - Not updating cover photo",self.scrollSpeed,ThreasholdSpeedForCoverPhotoUpdate);
        return;
    }
    self.shouldUpdateCoverPhotoOnSlowLoop = NO;

    [self loadCoverPhotoForUser:user completion:^(UIImage *image){
       dispatch_async(dispatch_get_main_queue(),^{self.coverPhotoImageView.image = image;}
}];

【问题讨论】:

    标签: ios objective-c uiview uiscrollview nstimer


    【解决方案1】:

    我不会使用NSTimer,而是使用UIScrollView delegate

    计算滚动速度:

    - (void)scrollViewDidScroll:(UIScrollView *)scrollView
    {
        CGFloat scrollSpeed = scrollView.contentOffset.y - previousScrollViewYOffset;
        previousTableViewYOffset = scrollView.contentOffset.y;
    }
    

    那么你可以这样做:

    for( UIViewSubclass *subview in scrollView ){
        subView.shouldUpdateCoverPhoto = scrollSpeed < kMaxScrollSpeed;
    }
    

    【讨论】:

    • 我不能在这种特殊情况下,因为我需要一个更通用的解决方案(不仅适用于滚动视图)。我将发布一个我想出的可能的解决方案。
    • 您能否详细说明为什么需要更通用的解决方案,例如没有滚动视图。那么他们滚动速度如何?
    • 我在视图内的视图内有一个视图等。没有办法将滚动速度滴入可能想要处理此类事件的每个可能的子视图。此外,自定义视图可能不知道它的容器——它可能会在某些情况下决定从磁盘或网络获取资源在它不会显示的情况下是徒劳的——例如,如果视图“飞”出屏幕。这是我面临的一个特定用例
    【解决方案2】:

    UIScrollView委托方法怎么样:

    – scrollViewWillEndDragging:withVelocity:targetContentOffset:?
    

    这不是你想要的吗?

    【讨论】:

    • 那当然是最好的,但在这种特殊情况下我没有这个选项。我需要一个更通用的解决方案
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-04-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-12-06
    • 2014-05-13
    • 1970-01-01
    相关资源
    最近更新 更多