Undo NSTimers associated with UITableViewCells when they go to screen

I implement a UITableView from UIImageView cells, each of which is periodically updated every 5 seconds through NSTimer . Each image is downloaded from the server in the background thread, and from this background thread I also update the user interface by displaying a new image by calling performSelectorOnMainThread . So far so good.

I noticed that the number of threads grows over time, and the user interface becomes unresponsive. So I want to nullify NSTimer if the cell leaves the screen. What delegation methods in a UITableView should be used for efficient use?

The reason I associate NSTimer with each cell is because I do not want the image transition to occur simultaneously for all cells. Are there other ways to do this, by the way? For example, is it possible to use only one NSTimer ?

(I cannot use SDWebImage because my requirement is to display a set of images in a loop downloaded from the server)

// In 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]; } } 

// In 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) { }]; } 
+4
source share
2 answers

If you correctly manage memory and delete reusable cells, you can subclass UITableViewCell and override its method - prepareForReuse , to stop the timer.

In addition, as @lnfaziger points out, if you want to immediately stop the timer when a cell is removed from the table view, you can also override its willMoveToSuperview: and / or didMoveToSuperview: and check if its superview nil - if so, the cell is deleted, so you can stop the timer.

+4
source

willMoveToSuperview: and / or didMoveToSuperview: do not work on ios 6.0

from ios 6.0 you have the following UITableViewDelegate method

 - (void)tableView:(UITableView *)tableView didEndDisplayingCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath 

Use this method to detect when a cell is removed from the table view, since it is against the control of the view itself to see when it appears or disappears.

+6
source

Source: https://habr.com/ru/post/1431994/


All Articles