CollectionView按钮/图像并没有及时刷新问题

时间:2013-07-04 21:29:54

标签: ios objective-c uicollectionview uicollectionviewcell

我有一个带有UICollectionViewFlowLayout的collectionView,具有一定的可重用性:

- (CategoryCell*)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
    CategoryCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"CategoryCell" forIndexPath:indexPath];
    [cell.actIn startAnimating];
    cell.cellElementRepresentation = [self.localCategoriesObjects objectAtIndex:indexPath.row];
    [cell tryToShow]; //this is a important method to my problem

    return cell;
}

我评论了你tryToShow方法。我认为这是一个问题。当我滚动到列表中不可见的元素时,我可以先看到“旧”元素,然后是新元素。这是为什么?我的tryToShow方法基本上就是下载管理器。我试着在评论中描述它。这是代码:

-(void)tryToShow {
    NSString* imageFile = self.linkToImageFileSavedOnDisk //This is my local file saved in documentsDirectory.

    if([[NSFileManager defaultManager] fileExistsAtPath:imageFile]) {
        [self.overlayButton setBackgroundImage:[UIImage imageWithContentsOfFile:imageFile] forState:UIControlStateNormal];
        [self disableActIn]; //Here i stop and remove activity indicator.
    } else {
        // Here i fire NSURLConnection and try to download. When NSURLConnection finished i put image to overlayButton.
    }
}

这是委托方法:

-(void)connectionDidFinishLoading:(NSURLConnection *)connection {
     //Here do some stuff to convert Data into UIImage... not important.
     [self.overlayButton setBackgroundImage:object forState:UIControlStateNormal];
}

overlayButton是UICollectionViewCell上的一个按钮。我有一个自定义类。

我无法理解。滚动后,如何从indexPath.row(例如1)成像?新成功下载后,图像会被新图像替换,但现在已经很晚了。

2 个答案:

答案 0 :(得分:1)

正如OP提到的,问题似乎是你设置backgroundImage为时已晚。所以我会尝试这些修改:

  1. 首先,在设置新值之前清除您的单元格。由于您正在重复使用单元格,旧值(文本和图像)仍将出现在单元格子视图中。将这些值设置为nil将清除您的单元格。

  2. 实施一种机制来验证或使图像请求的结果无效,因为可能会得到结果太晚,可能不再需要。最糟糕的是,您可以将图像设置为不再与您的数据相对应。在设置下载的图像之前,您应该检查此图像是否与当前显示的数据一致。

  3. 在开始图像请求之前稍等一下如果您有大量的单元格,您应该认为当用户快速滚动集合时,您可以启动大量图像请求可能永远不会显示。我会在开始新请求之前稍等一会儿,并检查该单元格是否已被重新使用,以避免此行为。

  4. 使用NSURLRequest并将cachePolicy属性配置为NSURLRequestReturnCacheDataElseLoad。这将存储图像的响应,无需显式保存图像保存图像并检查图像是否存在。

答案 1 :(得分:0)

我认为您需要在启动Web请求的else子句中将self.overlayButton的背景图像设置为nil。

[self.overlayButton setBackgroundImage:nil forState:UIControlStateNormal];

这样,当用户滚动到单元格时,单元格似乎不会加载图像。或者,如果加载速度不够快(它应该加载),您可以在collectionView:didEndDisplayingCell:forItemAtIndexPath:委托方法中将背景图像设置为nil。

但我发现的一个问题是,每次调用NSURLConnection时,您都会创建重复的tryToShow个对象,即用户向下滚动然后重新访问顶部的单元格。

正如@ lucaslt89建议的那样,你可以创建一个单元格字典,而不是使用默认的出列。如果这样做,请确保您在单元格上具有URL连接对象的属性,并在开始新单元之前检查它。

或者,您可能希望创建在视图控制器中创建的任何NSURLConnection对象的字典,并将Web请求代码移动到视图控制器中。如果需要Web请求,视图控制器将首先检查字典中是否已经存在Web请求。请求完成后,请求对象将从字典中删除。这将是理想的方法,因为单元格不负责创建自己的数据。在UICollectionView中,细胞必须快速改变角色,将特定细胞与某些数据相关联是不明智的,除非细胞真的很少。

无论哪种方式,您都可以避免为同一图片创建多个网址请求。

希望这有帮助!