下载完成后,使用AFNetworking更新UITableViewCell

时间:2014-04-16 21:30:04

标签: ios objective-c uitableview afnetworking

在我们的应用程序中,我们有一个免费杂志,用户可以下载PDF格式。如果他们没有下载问题,则UITableViewCell图片的alpha值较低,以便用户可以看到它未下载。

如果您点按一个单元格,它将开始使用AFHTTPRequestOperation下载,一旦完成,您可以使用QuickLook查看PDF。

我遇到的问题是,当用户启动下载,然后滚动然后返回时,他们点击的UITableViewCell会以某种方式丢失它正在下载的引用,因此不会更新{ {1}}或在下载完成后将alpha更改为1.0。我不能为我的生活弄清楚为什么UIProgressView不等于:

[[tableView indexPathForCell:cell] isEqual:indexPath]

如果我开始下载,然后在我的tableView中向下滚动,我的- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { PUCViewpointItem *item = [self.items objectAtIndex:indexPath.row]; // Check to see if we are already on the row that is activated if (indexPath.row == self.selectedIndexPath.row) { // File Path NSString *path = [self itemPath:item]; // Should we read the issue if (item.isDownloaded && path) { item.downloadPath = path; [self readIssue:item]; return; } // TableView Cell PUCViewpointTableViewCell *cell = (PUCViewpointTableViewCell *)[tableView cellForRowAtIndexPath:indexPath]; if (!path) { Utility *utility = [[Utility alloc] init]; NSURLRequest *request = [NSURLRequest requestWithURL:item.url]; AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request]; NSString *localPath = [[utility localDirectory] stringByAppendingFormat:@"/%@.pdf", item.name]; operation.outputStream = [NSOutputStream outputStreamToFileAtPath:localPath append:NO]; [operation setDownloadProgressBlock:^(NSUInteger bytesRead, long long totalBytesRead, long long totalBytesExpectedToRead) { float totalProgress = (float)totalBytesRead/totalBytesExpectedToRead; if ([[tableView indexPathForCell:cell] isEqual:indexPath]) { cell.progressView.hidden = NO; cell.progressView.progress = totalProgress; item.isDownloading = YES; item.isDownloaded = NO; item.progress = totalProgress; } }]; [operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) { if ([[tableView indexPathForCell:cell] isEqual:indexPath]) { cell.fullImage.alpha = 1.0f; cell.progressView.hidden = YES; item.isDownloaded = YES; item.isDownloading = NO; } NSLog(@"%d == %d", [tableView indexPathForCell:cell].row, indexPath.row); } failure:^(AFHTTPRequestOperation *operation, NSError *error) { if ([[tableView indexPathForCell:cell] isEqual:indexPath]) { cell.progressView.hidden = YES; item.isDownloading = NO; item.isDownloaded = NO; } }]; [operation start]; } return; } NSIndexPath *oldIndexPath = self.selectedIndexPath; self.selectedIndexPath = indexPath; [tableView beginUpdates]; [tableView endUpdates]; // Which way are we scrolling? UITableViewScrollPosition position; if (indexPath.row == 0 || (oldIndexPath && oldIndexPath.row < indexPath.row)) { position = UITableViewScrollPositionTop; } else { position = UITableViewScrollPositionBottom; } [self.tableView scrollToRowAtIndexPath:indexPath atScrollPosition:position animated:YES]; } 语句将记录类似NSLog的内容,这是没有意义的。

我有什么想法可以解决这个问题吗?

2 个答案:

答案 0 :(得分:2)

我很好奇你的情况,所以我写了一个小测试项目,你可以在这里找到它:https://github.com/mrojas/MRTableViewTest

基本上,解决问题的方法是:

  • 在项目类
  • 中放置逻辑以下载项目
  • 使该单元格成为该项目的代表,以获得有关进度/完成情况的通知
  • 滚动(重复使用)单元格时,在其上设置项目就足够了。他们计算当前状态并将自己设定为代表。

检查项目,尝试一下,如果您有疑问,请告诉我。

我没有使用AFNetworking,而是模拟了一些需要10秒钟完成的任务,时间间隔为2秒。

答案 1 :(得分:1)

我认为您必须将某个地方(如NSMutableArray实例变量)存储在您正在下载的indexPath中。所以你可以这样做:

-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
        if( [indexArray indexOfObject:indexPath] != NSNotFound )
        {
            // alpha for downloading
        }    
    }

在AFNetworking完成块中,您应该从indexArray中删除此indexPath。

正如评论所说,单元格不可靠存储任何类型的信息,因为滚动时它们会被重新分配

   @interface ViewController ()
    {
        NSMutableArray *_indexArray;
    }

    @end

    @implementation ViewController

    - (void)viewDidLoad
    {
        [super viewDidLoad];
        // Do any additional setup after loading the view, typically from a nib.
        UITableView *table = [[UITableView alloc] initWithFrame:self.view.frame style:UITableViewStylePlain];
        table.delegate = self;
        table.dataSource = self;
        _indexArray = [@[] mutableCopy];
        [self.view addSubview:table];
    }

    - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section;
    {
        return 50;
    }

// called when you scroll to new cells or when reloadData is called
    - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath;
    {
        UITableViewCell *cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"default"];
        cell.textLabel.textColor = [UIColor blueColor];

        // red color if I'm downloading, else blue
        if ([_indexArray indexOfObject:indexPath] != NSNotFound) {
            cell.textLabel.textColor = [UIColor redColor];
        }
        cell.textLabel.text = @"cell in the table";
        return cell;
    }

    - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath;
    {
        [_indexArray addObject:[indexPath copy]];
        NSLog(@"downloading...");
        UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
        cell.textLabel.textColor = [UIColor redColor]; // update UI temporary (until scroll)

            // HD Image so I can scroll up and down for testing
        NSString *res = @"http://res.cloudinary.com/******/image/upload/*****/Motorola_Razr_HD_Cam_Sample_7_ftzrj0.jpg";
            // custom class for download
        [[PLSApi api] downloadDataAtURL:[NSURL URLWithString:res] withBlock:^(NSData *data) {
            // download complete
            [_indexArray removeObject:indexPath];
            cell.textLabel.textColor = [UIColor blueColor]; // update UI
            NSLog(@"finished...");
        }];
    }