Ios 使用NSTimer或CADisplayLink查找UIView的移动速度

Ios 使用NSTimer或CADisplayLink查找UIView的移动速度,ios,objective-c,uiview,uiscrollview,nstimer,Ios,Objective C,Uiview,Uiscrollview,Nstimer,我有一个快速滚动的UIScrollView,其中包含许多视图,这些视图在重用时会更新 当scrollview快速滚动时,我希望视图忽略它们可能需要做的任何新绘图(这需要从磁盘获取信息,如图像等) 我考虑创建一个CADisplayLink(或者在本例中是一个NSTimer)并计算在keywindow中更改的视图位置,如下所示 - (void)setupUpdateTimer { self.shouldUpdateCoverPhoto = YES; self.previousFram

我有一个快速滚动的UIScrollView,其中包含许多视图,这些视图在重用时会更新

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

我考虑创建一个CADisplayLink(或者在本例中是一个NSTimer)并计算在keywindow中更改的视图位置,如下所示

- (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;
    }
}
-(无效)setupUpdateTime
{
self.shouldUpdateOverphoto=是;
self.previousFrame=CGRectNull;
NSTimer*timer=[NSTimer timerWithTimeInterval:UpdateInterval目标:自选择器:@selector(timerUpdate:)userInfo:nil repeats:YES];
[[NSRunLoop mainlunloop]addTimer:timer forMode:NSDefaultRunLoopMode];
self.updateTimer=计时器;
}
-(无效)timerUpdate:(NSTimer*)计时器
{
CGRect currentFrame=[[UIApplication sharedApplication].keyWindow convertRect:self.frame fromView:self.superview];
CGRect previousFrame=self.previousFrame;
self.previousFrame=当前帧;
if(CGRectEqualToRect(前一帧,CGRectNull))
{
self.shouldUpdateOverphoto=是;
返回;
}
CGFloat distance=ABS(currentFrame.origin.y-previousFrame.origin.y);
CGFloat速度=ABS(距离/更新间隔);
DLog(@“速度为%f”,速度);
如果(速度<1000)
{
self.shouldUpdateOverphoto=是;
}否则{
self.shouldUpdateOverphoto=否;
}
}
但是,当视图位置变化非常快时,不会定期调用计时器回调

因此,我不知道视图位置的变化是否足够规律

有更好的方法吗

编辑

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

-(无效)setupUpdateTime
{
self.shouldUpdateOverphotonSloop=否;
self.previousFrame=CGRectNull;
self.scrollSpeed=0;
CADisplayLink*displayLink=[CADisplayLink displayLink WITHTARGET:自选择器:@selector(checkNeedsUpdate:)];
[displayLink addToRunLoop:[NSRunLoop mainRunLoop]forMode:NSRunLoopCommonModes];
}
-(无效)检查需要更新日期:(CADisplayLink*)链接
{
CGRect currentFrame=[[UIApplication sharedApplication].keyWindow convertRect:self.frame fromView:self.superview];
CGRect previousFrame=self.previousFrame;
self.previousFrame=当前帧;
if(CGRectEqualToRect(前一帧,CGRectNull))
{
self.scrollSpeed=0;
返回;
}
CGFloat distance=ABS(currentFrame.origin.y-previousFrame.origin.y);
CGFloat duration=link.duration;
CGFloat速度=ABS(距离/持续时间);
self.scrollSpeed=速度;
if(self.scrollSpeedThreasholdSpeedForCoverPhotoUpdate&&self.coverPhotoImageView.image!=nil)
{
self.shouldUpdateOverphotonSloop=YES;
//DLog(@“滚动速度%f大于threshold%d-不更新封面照片”,self.scrollSpeed,thresholdspeedforcoverphotoupdate);
返回;
}
self.shouldUpdateOverphotonSloop=否;
[self-loadCoverPhotoForUser:用户完成:^(UIImage*图像){
dispatch_async(dispatch_get_main_queue(),^{self.coverPhotoImageView.image=image;}
}];

如何
UIScrollView
委托方法:

– scrollViewWillEndDragging:withVelocity:targetContentOffset:?

这不是您想要的吗?

我不会使用
NSTimer
,而是使用
UIScrollView委托进行此操作

要计算滚动速度,请执行以下操作:

- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
    CGFloat scrollSpeed = scrollView.contentOffset.y - previousScrollViewYOffset;
    previousTableViewYOffset = scrollView.contentOffset.y;
}
然后你可以做:

for( UIViewSubclass *subview in scrollView ){
    subView.shouldUpdateCoverPhoto = scrollSpeed < kMaxScrollSpeed;
}
for(滚动视图中的UIViewSubclass*子视图){
subView.shouldUpdateOverphoto=scrollSpeed
这当然是最好的,但在这种情况下我没有这个选项。我需要一个更通用的解决方案在这种情况下我不能,因为我需要一个更通用的解决方案(不仅仅是滚动视图)。我会发布我想出的一个可能的解决方案。你能详细说明一下为什么你需要一个更通用的解决方案,比如没有滚动视图。那么它们的滚动速度如何?我在视图中有一个视图,在视图中有一个视图等。没有办法将滚动速度缓慢地传递到每个可能要处理此类事件的子视图。还有一个自定义视图I don’我不知道它的容器——在某些情况下,它可能会认为从磁盘或网络获取资源在它不会显示的情况下是徒劳的——例如,如果视图“飞出”屏幕。这是我面临的特定用例
for( UIViewSubclass *subview in scrollView ){
    subView.shouldUpdateCoverPhoto = scrollSpeed < kMaxScrollSpeed;
}