我有一个问题

我有一个带有静态200个单元格的简单UICollectionView,可从Flickr加载图像。

我的CellForItemAtIndexPath看起来像这样:

- (UICollectionViewCell *)collectionView:(UICollectionView *)cv cellForItemAtIndexPath:(NSIndexPath *)indexPath {
    UICollectionViewCell *cell = [cv dequeueReusableCellWithReuseIdentifier:@"FlickrCell" forIndexPath:indexPath];
    cell.backgroundColor = [self generateRandomUIColor];

    if(![[cell.subviews objectAtIndex:0] isKindOfClass:[PFImageView class]])
    {
        NSURL *staticPhotoURL = [self.context photoSourceURLFromDictionary:[self.photos objectAtIndex:indexPath.row] size:OFFlickrSmallSize];
        PFImageView *imageView = [[PFImageView alloc] initWithFrame:CGRectMake(0, 0, cell.frame.size.height, cell.frame.size.width) andImageURL:staticPhotoURL andOwningCell:cell];
        [cell addSubview:imageView];
    }
    return cell;
}

PFImageView是UIImageView的子类,它在后台线程上加载Flickr照片URL,然后在主线程上更新其自身的图像-正常工作。

逻辑非常简单-如果没有一个可出队,我将创建一个单元。

如果单元格(我希望它已经出列并且已经具有PFImageView)没有具有PFImageView,则为该单元分配并初始化一个imageView并将其添加为该单元格的子视图。

因此,我希望如果单元已经出队,它应该已经有一个PFImageView作为子视图,并且因为我们不应该进入if语句来创建一个新的imageView并启动一个新的照片下载请求

相反,我看到的是UICollectionView顶部和底部的单元格暂时“不在屏幕上”-当它们重新显示在屏幕上时,它们并没有被重用,并且似乎创建了一个新的单元格并刷新了图片。

1)创建单元后,如何获得静态图像(即,当单元略微偏离屏幕时不刷新)。

2)为什么不重复使用细胞?

非常感谢您的宝贵时间。

约翰

最佳答案

我看到几个潜在的问题:

  • 您正在专门查看要添加的子类的单元格索引0。 UICollectionViewCell可能有其他视图作为子视图,因此您不能仅假设唯一(或第一个)子视图是您添加的子视图。
  • 我看不到您正在调用registerClass:forCellWithReuseIdentifier:或registerNib:forCellWithReuseIdentifier:正确使用出队(https://developer.apple.com/library/ios/documentation/uikit/reference/UICollectionViewCell_class/Reference/Reference.html)是其中之一。
  • 仅在必须构造PFImageView的情况下,才设置PFImageView的URL。使可重用视图出队的想法是,您将只构造所需视图的一小部分,并且UITableView将在它们移出屏幕时对其进行回收。即使您不构造新内容,也需要重置请求的indexPath的值。

  • 如果您的情况像您描述的那样简单,则可以将PFImageView添加到出列的UICollectionView的contentView属性中,从而摆脱困境。

    在您的控制器中:
    // solve problem 2
    [self.collectionView registerClass:[UICollectionViewCell class] forReuseIdentifer:@"FlickrCell"];
    

    在collectionView:cellForItemAtIndexPath中
    UICollectionViewCell *cell = [cv dequeueReusableCellWithReuseIdentifier:@"FlickrCell" forIndexPath:indexPath];
    cell.backgroundColor = [self generateRandomUIColor];
    
    // solve problem 1 by looking in the contentView for your subview (and looping instead of assuming at 0)
    PFImageView *pfImageView = nil;
    for (UIView *subview in cell.contentView.subviews)
    {
        if ([subview isKindOfClass:[PFImageView class]])
        {
            pfImageView = (PFImageView *)subview;
            break;
        }
    }
    
    NSURL *staticPhotoURL = [self.context photoSourceURLFromDictionary:[self.photos objectAtIndex:indexPath.row] size:OFFlickrSmallSize];
    if (pfImageView == nil)
    {
        // No PFImageView, create one
        // note the use of contentView!
        pfImageView = [[PFImageView alloc] initWithFrame:CGRectMake(0, 0, cell.contentView.frame.size.height, cell.frame.size.width) andImageURL:staticPhotoURL andOwningCell:cell.contentView];
        [cell.contentView addSubview:pfImageView];
    }
    else
    {
        // Already have recycled view.
        // need to reset the url for the pfImageView. (Problem 3)
        // not sure what PFImageView looks like so this is an e.g. I'd probably remove the
        // URL loading from the ctr above and instead have a function that loads the
        // image. Then, you could do this outside of the if, regardless of whether you had
        // to alloc the child view or not.
        [pfImageView loadImageWithUrl:staticPhotoURL];
        // if you really only have 200 static images, you might consider caching all of them
    }
    return cell;
    

    对于不太简单的情况(例如,我想在视觉上布置单元格,或在内容中有多个子级的情况),我通常使用Interface Builder自定义UICollectionViewCell。
  • 在项目中创建UICollectionViewCell的子类(在您的情况下,将其称为PFImageCell)。
  • 为要在初始化中更改的视图(在您的情况下为UIImageView)向该子类添加IBOutlet属性。@property (nonatomic, assign) IBOutlet UIImageView *image;
  • 在Interface Builder中,为UITableView创建一个原型单元。
  • 在该原型单元的属性表中,将UICollectionViewCell子类标识为该类。
  • 在属性表中给原型单元一个标识符(重用标识符)。
  • 将接口构建器中的视图子级添加到原型单元(此处为UIImageView)。
  • 使用IB将IBOutlet属性映射到添加的UIImageView
  • 然后,在cellForRowAtIndexPath中出队时,将出队结果转换为子类(PFImageCell),并设置IBOutlet属性实例的值。在这里,您将为UIImageView加载正确的图像。
  • 关于ios - 滚动期间重复使用UICollectionViewCells,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/21614731/

    10-12 14:35