取消与UITableViewCells关联的NSTimers,当它们离开屏幕时

Nim*_*sri 5 uitableview nstimer ios

我实现UITableViewUIImageView细胞,其中的每一个通过周期性地刷新本身每5秒NSTimer.每个图像都是从后台线程中的服务器加载的,并且从后台线程我还通过调用更新UI,显示新图像performSelectorOnMainThread.到现在为止还挺好.

我注意到的问题是线程数随着时间的推移而增加,UI变得无响应.因此,我想NSTimer在一个单元格离开屏幕时无效.UITableView我应该使用哪种委派方法来有效地执行此操作?

之所以我将NSTimer每个单元格关联起来是因为我不希望所有单元格同时发生图像转换.顺便说一句,有没有其他方法可以做到这一点?例如,是否可以只使用一个NSTimer

(我无法使用,SDWebImage因为我的要求是在从服务器加载的循环中显示一组图像)

//在MyViewController.m中

 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
    {
        ...
        NSTimer* timer=[NSTimer scheduledTimerWithTimeInterval:ANIMATION_SCHEDULED_AT_TIME_INTERVAL 
                                                    target:self 
                                                  selector:@selector(updateImageInBackground:) 
                                                  userInfo:cell.imageView 
                                                   repeats:YES];
        ...
    }

- (void) updateImageInBackground:(NSTimer*)aTimer
{  
    [self performSelectorInBackground:@selector(updateImage:)
                       withObject:[aTimer userInfo]];
}  

- (void) updateImage:(AnimatedImageView*)animatedImageView 
{      
    @autoreleasepool { 
        [animatedImageView refresh];
    }
}  
Run Code Online (Sandbox Code Playgroud)

//在AnimatedImageView.m中

 -(void)refresh
    {
        if(self.currentIndex>=self.urls.count)
            self.currentIndex=0;

    ASIHTTPRequest *request=[[ASIHTTPRequest alloc] initWithURL:[self.urls objectAtIndex:self.currentIndex]];
    [request startSynchronous];

    UIImage *image = [UIImage imageWithData:[request responseData]];

    // How do I cancel this operation if I know that a user performs a scrolling action, therefore departing from this cell.
    [self performSelectorOnMainThread:@selector(performTransition:)
                       withObject:image
                    waitUntilDone:YES];
}

-(void)performTransition:(UIImage*)anImage
{
    [UIView transitionWithView:self duration:1.0 options:(UIViewAnimationOptionTransitionCrossDissolve | UIViewAnimationOptionAllowUserInteraction) animations:^{ 
        self.image=anImage;
        currentIndex++;
    } completion:^(BOOL finished) {
    }];
}
Run Code Online (Sandbox Code Playgroud)

Mer*_*ert 6

willMoveToSuperview:和/或didMoveToSuperview:不适用于ios 6.0

从ios 6.0开始,您有以下UITableViewDelegate方法

- (void)tableView:(UITableView *)tableView didEndDisplayingCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
Run Code Online (Sandbox Code Playgroud)

使用此方法可以检测何时从表视图中删除单元格,而不是监视视图本身以查看它何时出现或消失.


小智 5

如果您适当地管理内存并使可重复使用的单元出队,则可以继承UITableViewCell并覆盖其- prepareForReuse方法以停止计时器。

此外,正如@lnfaziger指出的那样,如果要在从表视图中删除该单元格时立即停止计时器,则还可以覆盖其willMoveToSuperview:和/或didMoveToSuperview:方法,并检查其superview参数是否为nil-如果是,则该单元格为删除,因此您可以停止计时器。

  • 请注意,当一个单元格离开屏幕时,不会调用此方法,而是在一个单元格将被重用时调用。这可能会使仍在等待计时器运行的单元格在队列中等待。如果您需要在它们离开屏幕后立即取消它们,请改用`willMoveToSuperview`或`didMoveToSuperview`。 (3认同)