SoFunction
Updated on 2025-04-12

Problems and solutions for iOS tableView pull-up refresh displaying download progress

1. After clicking the download button, the downLoad method of afnetworking is called. The specific code is as follows

@interface ViewController ()<UITableViewDelegate,UITableViewDataSource>
{
  XLCircleProgress *_circle;
  CGFloat _progress;
}
@property (strong,nonatomic) NSURLSessionDownloadTask *downloadTask;
@property (strong,nonatomic) UITableView *tableView;
@property (strong,nonatomic) NSMutableArray *dataSource;
@end
- (void)request:(NSInteger)index{
  //download  NSURL *URL = [NSURL URLWithString:@"http://song./upload/media/e366a607d222442f83ed7028c4d7118e_20170227110100.mp4"];
  NSURLRequest *request = [NSURLRequest requestWithURL:URL];
  AFHTTPSessionManager *manger = [AFHTTPSessionManager manager];
   = [AFJSONResponseSerializer serializer];
  _downloadTask= [manger downloadTaskWithRequest:request progress:^(NSProgress * _Nonnull downloadProgress) {
    NSLog(@"%f",);
    _progress = ;
    // Open an asynchronous thread and put it in the main queue to refresh the data    dispatch_async(dispatch_get_main_queue(), ^{
      [self reloadCell:index];
    });
  } destination:^NSURL *(NSURL *targetPath, NSURLResponse *response) {
    //Get the sandbox cache path    NSURL * documentsDirectoryURL = [[NSFileManager defaultManager] URLForDirectory:NSCachesDirectory inDomain:NSUserDomainMask appropriateForURL:nil create:NO error:nil];
    return [documentsDirectoryURL URLByAppendingPathComponent:[response suggestedFilename]];
  } completionHandler:^(NSURLResponse *response, NSURL *filePath, NSError *error) {
    if (error) {
      NSLog(@"fail");
    } else {
       NSLog(@"success");
    }
  }];
  [_downloadTask resume];
}
- (void)reloadCell:(NSInteger)index{
  // Modify the corresponding data source  NSMutableDictionary *dic = [[NSMutableDictionary alloc]init];
  [dic addEntriesFromDictionary:[index]];
  [dic removeObjectForKey:@"progress"];
  [dic setObject:@(_progress) forKey:@"progress"];
  [ replaceObjectAtIndex:index withObject:dic];
  // Refresh a cell  NSIndexPath *indexPath = [NSIndexPath indexPathForRow:index inSection:0];
  [ reloadRowsAtIndexPaths:[NSArray arrayWithObjects:indexPath, nil] withRowAnimation:UITableViewRowAnimationNone];
}

question:If it is, but one download and refresh is OK, but multiple tasks are performed at the same time, data exchange will be carried out back and forth

Solution 1:I checked a lot of information online and found that the cell cannot be refreshed in real time, whether it is a single or multiple, because the refresh will cause the interface to jump. Of course, is there any other way to solve it? This is also possible.

Solution 2:Directly assign values ​​in real time (find the corresponding cell) in asynchronously, so as to avoid interface jumps caused by refreshing the cell. For details, please refer to the code:

But this still exists. The cell progress bar that has been downloaded during refreshing will be zeroed. After refreshing, it will be restored to the normal value. However, if you refresh after downloading, it will be 0 directly. This should be caused by cell reuse. Then let’s solve the problem of refreshing and zeroing.

// Find the indexPath of the corresponding cellNSIndexPath *indexPath = [NSIndexPath indexPathForRow:index inSection:0];
MyTableViewCell *cell = (MyTableViewCell *)[_tableView cellForRowAtIndexPath:indexPath];
    dispatch_async(dispatch_get_main_queue(), ^{
  // This is said online that this will consume CPU resources. After I personally test it, it basically costs no resources. I am afraid of memory leaks and other problems. However, I have not caught it yet. If I find something inappropriate in the future, I will correct it.       = _progress;
//      [self reloadCell:index];
    });

The following is the cell reuse mechanism. If the initial value is not paid for the progress bar, there will be no problem of zeroing when refreshing.

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
  MyTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"cell" forIndexPath:indexPath];
   = NO;
   = [][@"title"];
//   = [[][@"progress"] floatValue];
  return cell;
}