带有进度条下载更新的自定义 UITableViewCell

Posted

技术标签:

【中文标题】带有进度条下载更新的自定义 UITableViewCell【英文标题】:Custom UITableViewCell with Progress Bar download update 【发布时间】:2014-01-15 09:28:56 【问题描述】:

我正在尝试使用进度条加载更新每个表格单元格,但我被卡住了。 我为具有以下属性的表格视图创建了一个自定义单元格:

@interface OFPTableCell : UITableViewCell 
@property (nonatomic, weak) IBOutlet UILabel *textLabel;
@property (nonatomic, weak) IBOutlet UILabel *detailTextLabel;
@property (weak, nonatomic) IBOutlet UIImageView *imageView;
@property (weak, nonatomic) IBOutlet UIProgressView *progressView;
@end;

在@synthesize 它们之后,现在我在每个表格单元格中都有一个预期的进度条。

问题是,当我尝试使用加载进度条更新第一个单元格时,它什么也不做,或者设置为 0 或完整的进度条。 请注意,下载过程运行正常。

您可能会在下面找到我尝试更新进度条的代码:

 - (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask          *)downloadTask didWriteData:(int64_t)bytesWritten
  totalBytesWritten:(int64_t)totalBytesWritten totalBytesExpectedToWrite:    (int64_t)totalBytesExpectedToWrite


      dispatch_async(dispatch_get_main_queue(), ^
      NSIndexPath *indexPath = [NSIndexPath indexPathForRow:0 inSection:0];
      OFPTableCell *cell = (OFPTableCell*)[self tableView:self.tableViewCache    cellForRowAtIndexPath:indexPath];
      cell.progressView.progress=(double)totalBytesWritten /  (double)totalBytesExpectedToWrite;
);


下面是 cellForRowAtIndexPath 方法:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath


     OFPTableCell *cell = [self.tableViewCache dequeueReusableCellWithIdentifier:@"Cell"];



    OFPVideoDetails *vd = [someArray objectAtIndex:indexPath.row];
    cell.textLabel.text=vd1;
    cell.detailTextLabel.text=vd2;

    CGSize size = 65,53;
    cell.imageView.image =[self imageWithImage:[UIImage       imageWithContentsOfFile:vd.imageUrl] scaledToSize:size];



     cell.delegate = self;



 return cell;
  

【问题讨论】:

【参考方案1】:

直接调用方法tableView:cellForRowAtIndexPath:是非常糟糕的做法,因为该单元格可能同时不存在,并且可能是您遇到的错误的原因。

基本上你应该用另一种方式来做:添加一个双精度数组:

double progressValues[30]; // 30 is the count of rows on your tableView, you can set the size dynamically

并像这样使用它:

- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didWriteData:(int64_t)bytesWritten 
totalBytesWritten:(int64_t)totalBytesWritten totalBytesExpectedToWrite:
(int64_t)totalBytesExpectedToWrite

  dispatch_async(dispatch_get_main_queue(), ^
  NSIndexPath *indexPath = [NSIndexPath indexPathForRow:0 inSection:0];
  OFPTableCell *cell = (OFPTableCell*)[self tableView:self.tableViewCache    cellForRowAtIndexPath:indexPath];
  progressValues[indexPath.row] = (double)totalBytesWritten /  (double)totalBytesExpectedToWrite;
  [self.tableViewCache reloadData];
);

并在 dataSource 方法中添加这个字符串:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath

    //... your code...
    cell.progressView.progress = progressValues[indexPath.row];
    // ...
    return cell;

【讨论】:

还有一个问题,而不是 [self.tableViewCache reloadData];我可以使用 [self.tableViewCache reloadRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationNone]; ? 是的,当然你最好只重新加载一行,它会在当前时间发生变化。我在上面写的只是一般想法,没有考虑到这些细节:) 我得到 nil 在:cell.progressView.progress = progressValues[indexPath.row]; 但是如何识别我们正在为哪个单元格显示进度视图?【参考方案2】:

您应该在 OFPVideoDetails 中保留 (double)totalBytesWritten / (double)totalBytesExpectedToWrite 的值(在 OFPVideoDetails 中添加一个属性“progress”)。

然后重新加载- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didWriteData:(int64_t)bytesWritten totalBytesWritten:(int64_t)totalBytesWritten totalBytesExpectedToWrite: (int64_t)totalBytesExpectedToWrite中的单元格

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath

    OFPTableCell *cell = [self.tableViewCache dequeueReusableCellWithIdentifier:@"Cell"];
    OFPVideoDetails *vd = [someArray objectAtIndex:indexPath.row];
    cell.textLabel.text=vd1;
    cell.detailTextLabel.text=vd2;
    CGSize size = 65,53;
    cell.imageView.image =[self imageWithImage:[UIImage       imageWithContentsOfFile:vd.imageUrl] scaledToSize:size];
    cell.progressView.progress = vd.progress;
    cell.delegate = self;
    return cell;

【讨论】:

什么是 OFPVideoDetails?【参考方案3】:

对于 Swift 4.2

  func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didWriteData bytesWritten: Int64, totalBytesWritten: Int64, totalBytesExpectedToWrite: Int64) 

          DispatchQueue.main.async(execute: 
            let indexPath = IndexPath(row: 0, section: 0)
            let cell = self.tableView(self.tableViewCache, cellForRowAt: indexPath) as? OFPTableCell
            progressValues[indexPath.row] = Double(totalBytesWritten) / Double(totalBytesExpectedToWrite)
            self.tableViewCache.reloadData()
        )
    

【讨论】:

以上是关于带有进度条下载更新的自定义 UITableViewCell的主要内容,如果未能解决你的问题,请参考以下文章

当 UITableView 单元格中的进度条不可见时,如何更新它们

带有进度条的按钮 android

带有动画更改的自定义进度对话框的大小

CodePush自定义更新弹框及下载进度条

在每个 TableViewcell 中播放带有进度条的音频

uitableview中的ios进度条