我有问题,
我有一个简单的UICollectionView,带有静态200个单元,可以从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 :(得分:2)
UICollectionView
将重复使用单元格以获得最高效率。它不保证任何特定的重用或人口策略。有趣的是,似乎基于两个区域的整数幂来放置和移除单元格 - 例如在非视网膜iPad上,它可能会将您的滚动区域划分为1024x1024的区域,然后在它们过渡进出可见区域时填充和减少每个区域。但是,你不应该预测对其确切行为的任何期望。
此外,您对集合视图单元格的使用不正确。见the documentation。一个单元格至少有两个子视图 - backgroundView
和contentView
。因此,如果添加子视图,它将至少在索引2处,实际上,索引将是未定义的。在任何情况下,您都应该将子视图添加到contentView
,而不是添加到单元格本身。
执行您正在执行的操作的最常用方法是创建一个自定义UICollectionView
子类,其中包含PFImageView
。
答案 1 :(得分:1)
我不确定该细胞是否正在重复使用。它可能正在被重用,但子视图可能不存在。我的建议是创建一个PFImageViewCollectionViewCell类(UICollectionViewCell的子类)并将其注册为CollectionView Cell并尝试。如果我需要在单元格内部进行子视图,这就是我的行为和做法。
答案 2 :(得分:1)
我看到了几个潜在的问题:
您正在查看要添加的子类的单元格的索引0。 UICollectionViewCell可能有其他视图作为子视图,因此您不能只假设唯一(或第一个)子视图是您添加的视图。
我没有看到您正在调用registerClass:forCellWithReuseIdentifier:或registerNib:forCellWithReuseIdentifier:,正确使用dequeue(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。
@property (nonatomic, assign) IBOutlet UIImageView *image;
答案 3 :(得分:1)
尝试在此特定UIImageView
- (UICollectionViewCell *)collectionView:(UICollectionView *)cv cellForItemAtIndexPath:(NSIndexPath *)indexPath {
static int photoViewTag = 54353532;
UICollectionViewCell *cell = [cv dequeueReusableCellWithReuseIdentifier:@"FlickrCell" forIndexPath:indexPath];
cell.backgroundColor = [self generateRandomUIColor];
PFImageView *photoView = [cell.contentView viewWithTag:photoViewTag];
// Create a view
//
if (!photoView) {
photoView = [[PFImageView alloc] initWithFrame:CGRectMake(0, 0, cell.frame.size.height, cell.frame.size.width) andImageURL:staticPhotoURL andOwningCell:cell];
imageView.tag = photoViewTag;
[cell.contentView addSubview:imageView];
}
// Update the current view
//
else {
NSURL *staticPhotoURL = [self.context photoSourceURLFromDictionary:[self.photos objectAtIndex:indexPath.row] size:OFFlickrSmallSize];
photoView.imageURL = staticPhotoURL;
}
return cell;
}
我真的建议你创建自己的UICollectionViewCell
子类。
编辑:另外,请注意我使用了contentView
属性,而不是直接将其添加到单元格中。