Problems and Solutions of iOS tableView Pull up Refresh Display Download Progress

  • 2021-11-30 01:41:40
  • OfStack

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.90uncle.com/upload/media/e366a607d222442f83ed7028c4d7118e_20170227110100.mp4"];
  NSURLRequest *request = [NSURLRequest requestWithURL:URL];
  AFHTTPSessionManager *manger = [AFHTTPSessionManager manager];
  manger.responseSerializer = [AFJSONResponseSerializer serializer];
  _downloadTask= [manger downloadTaskWithRequest:request progress:^(NSProgress * _Nonnull downloadProgress) {
    NSLog(@"%f",downloadProgress.fractionCompleted);
    _progress = downloadProgress.fractionCompleted;
    //  Open 1 Asynchronous threads, put them in the home queue to refresh the data 
    dispatch_async(dispatch_get_main_queue(), ^{
      [self reloadCell:index];
    });
  } destination:^NSURL *(NSURL *targetPath, NSURLResponse *response) {
    // Get a 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(@" Failure ");
    } else {
       NSLog(@" Success ");
    }
  }];
  [_downloadTask resume];
}
- (void)reloadCell:(NSInteger)index{
  //  Modify the corresponding data source 
  NSMutableDictionary *dic = [[NSMutableDictionary alloc]init];
  [dic addEntriesFromDictionary:self.dataSource[index]];
  [dic removeObjectForKey:@"progress"];
  [dic setObject:@(_progress) forKey:@"progress"];
  [self.dataSource replaceObjectAtIndex:index withObject:dic];
  //  Refresh sth 1 A cell
  NSIndexPath *indexPath = [NSIndexPath indexPathForRow:index inSection:0];
  [self.tableView reloadRowsAtIndexPaths:[NSArray arrayWithObjects:indexPath, nil] withRowAnimation:UITableViewRowAnimationNone];
}

Problem: If yes, one download refresh is OK, but if multiple tasks are carried out at the same time, data will be exchanged back and forth

Solution 1: I checked a lot of information on the Internet and found that it is impossible to refresh cell in real time, whether it is single or multiple, because the refresh will appear the phenomenon of interface jumping. Of course, it is possible to solve it by other methods.

Solution 2: Assign values directly in asynchronous real time (find the corresponding cell), so as to avoid the phenomenon of interface jumping caused by refreshing cell. See the code for details:

However, this still exists. The downloaded cell progress bar will return to zero when refreshing, and will be restored to normal value after refreshing. However, if it is refreshed after downloading, it will be 0 directly, which should be caused by cell reuse, so the next step is to solve the problem of refreshing to zero.


//  Find the corresponding cell Adj. indexPath
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:index inSection:0];
MyTableViewCell *cell = (MyTableViewCell *)[_tableView cellForRowAtIndexPath:indexPath];
    dispatch_async(dispatch_get_main_queue(), ^{
  //  In this way, it is said on the Internet that it will cost cpu Resources, I pro-test, the basic cost of resources, there is fear of memory leaks and other issues, but now has not been caught, after the discovery of inappropriate places, and then add corrections 
      cell.progress.progress = _progress;
//      [self reloadCell:index];
    });

The following is the mechanism of cell reuse. If you don't pay the initial value for the progress bar in it, you won't have the problem of returning to zero when refreshing


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


Related articles: