1

我有一个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)图像可见?新的成功下载后,图像立即被新的替换,但这为时已晚。

4

2 回答 2

1

正如 OP 提到的,问题似乎是你设置backgroundImage得太晚了。所以我会尝试这个修改:

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

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

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

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

于 2013-07-07T04:25:52.057 回答
0

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

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

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

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

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

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

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

希望这可以帮助!

于 2013-07-07T04:26:47.887 回答