UITrogViewView在UITableViewCell上

时间:2015-03-23 01:59:29

标签: ios uitableview afnetworking-2 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;

}

我的downloadHelper:

- (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;
}

当我在第一个单元格中按下“下载”按钮时: enter image description here

当我向下滚动然后向上滚动时,它是第二个单元格: enter image description here

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

2 个答案:

答案 0 :(得分:6)

由于细胞被重复使用,您只是不能保持对细胞的弱引用并更新细胞的进展视图。至少,不是使用对表视图单元格的弱引用,而是使用索引路径,使用[tableView cellForRowAtIndexPath:indexPath]查找正确的单元格(这是一种UITableView方法,用于标识关联的单元格使用特定的NSIndexPath并且不应该与我们执行单元格出列/配置逻辑的类似命名的UITableViewDataSource方法混淆,并更新该单元格的进度视图(假设该单元格)甚至可见。)

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

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

请注意,许多天真的实现都考虑了上述所有要点,并决定放弃单元重用以简化问题。我不赞成这一点,但我认为这是一种根本误入歧途的做法。在我看来,应该有一个与视图对象分开的下载的适当模型。

答案 1 :(得分:4)

我在github上有一个小项目,基本上可以用不同的样式进度指示器做你想要的。我建立了一段时间,它完全采用Rob提到的方法:桌子和它的细胞由一个"模型支持"告诉单元格给定index他们的状态应该是什么。我还确保细胞可以重复使用。它可能对你有用:

https://github.com/chefnobody/StreamingDownloadTest