UITableViewCell上的UIProgressView

我正在使用AFNetworking从我的服务器上下载文件。 它工作正常。 但我有一个问题:当我向上或向下滚动时,我的ProgressView更新错误的单元格(UI,而不是数据)。 这是我的代码:

我的手机:

AFHTTPRequestOperation *operation; @property (weak, nonatomic) IBOutlet DACircularProgressView *daProgressView; - (IBAction)pressDown:(id)sender { AFAPIEngineer *apiEngineer = [[AFAPIEngineer alloc] initWithBaseURL:[NSURL URLWithString:AF_API_HOST]]; operation = [apiEngineer downloadFile:(CustomObject*)object withCompleteBlock:^(id result) { } errorBlock:^(NSError *error) { }]; __weak typeof(self) weakSelf = self; apiEngineer.afProgressBlock = ^(double progress, double byteRead, double totalByToRead) { [weakSelf.daProgressView setProgress:progress animated:YES]; }; } - (void)setDataForCell:(id)object{ } 

我的桌子:

 - (UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { CustomCell *cell = (CustomCell*)[tableView dequeueReusableCellWithIdentifier:NSStringFromClass([CustomCell class])]; cell.backgroundColor = [UIColor clearColor]; CustomObject *aObject = [listObject objectAtIndex:indexPath.row]; [cell setDataForCell: aObject]; return cell; } 

我的下载帮助:

 - (AFDownloadRequestOperation*)downloadFile:(CustomObject*)aObject withCompleteBlock:(AFResultCompleteBlock)completeBlock errorBlock:(AFResultErrorBlock)errorBlock{ NSString *link = URL; NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:link]]; NSString *path = [NSString databasePathWithPathComponent:[NSString stringWithFormat:@"%@.zip", @"noname"]]; AFDownloadRequestOperation *operation = [[AFDownloadRequestOperation alloc] initWithRequest:request targetPath:path shouldResume:YES]; [operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) { completeBlock(responseObject); } failure:^(AFHTTPRequestOperation *operation, NSError *error) { errorBlock(error); }]; [operation setProgressiveDownloadProgressBlock:^(AFDownloadRequestOperation *operation, NSInteger bytesRead, long long totalBytesRead, long long totalBytesExpected, long long totalBytesReadForFile, long long totalBytesExpectedToReadForFile) { float progressF = (float)totalBytesReadForFile / totalBytesExpectedToReadForFile; self.afProgressBlock(progressF, totalBytesReadForFile, totalBytesExpectedToReadForFile); }]; [operation start]; return operation; } 

当我按下第一个单元格中的“下载”button时: 在这里输入图像说明

当我向下滚动然后向上滚动,这是第二个单元格: 在这里输入图像说明

所以,我的问题是:如何更新UITableViewCell上的UIProgressView? 我的代码有什么问题?

由于单元格被重新使用,您不能只保留对单元格的弱引用并更新单元格的进度视图。 至less,不是对表视图单元使用弱引用,而是使用索引path,使用[tableView cellForRowAtIndexPath:indexPath]查找正确的单元格(这是一个UITableView方法,用于标识与特定NSIndexPath ,不应该和名为UITableViewDataSource方法在我们的单元出队/configuration逻辑中混淆),并更新单元格的进度视图(假设单元格是可见的)。

坦率地说,即使这样也是危险的,因为它假设下载过程中不可能添加或删除单元格。 (这显然不是一个合理的假设/约束放置在应用程序上。)坦率地说,每次想要更新下载进度,真的应该回到模型,查找正确的模型对象的基于NSIndexPath的问题,然后使用上述cellForRowAtIndexPath模式来查找并更新有问题的单元格。

请注意,这表示下载请求的启动可能不会由表视图单元启动。 就我个人而言,我维护一个模型对象,它包含一组要下载的文件,并将下载队列与其关联,而不是单元(尽pipe进度处理程序明显更新单元)。 简而言之,您需要UI(例如单元格)与驱动下载的模型之间的松散耦合关系。

请注意,许多天真的实现考虑了上述所有的点,并决定放弃细胞重用,以简化问题。 我不会说这个问题,但我认为这是一个根本性的错误的方法。 在我看来,一个应该有一个适当的模型下载独立于视图对象。

我有一个github上的小项目,基本上做你想要什么不同的风格进度指标。 我build立了一段时间,它使用了Rob提到的方法:表格及其单元格由一个“模型”支持,该模型告诉指定index处的单元格应该是什么状态。 我也确保细胞被重复使用。 这可能对您有些用处:

https://github.com/chefnobody/StreamingDownloadTest