Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/objective-c/24.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios 如何在自定义UICollectionViewCell上正确加载图像?_Ios_Objective C_Iphone_Uicollectionview_Uicollectionviewcell - Fatal编程技术网

Ios 如何在自定义UICollectionViewCell上正确加载图像?

Ios 如何在自定义UICollectionViewCell上正确加载图像?,ios,objective-c,iphone,uicollectionview,uicollectionviewcell,Ios,Objective C,Iphone,Uicollectionview,Uicollectionviewcell,我整个下午都在这里,我想不出来,所以你的帮助太棒了!我有一个自定义的UICollectionViewCell,我用动态创建的图像填充它。图像的路径存储在Parse中,查询完成后,我调用[self.collectionView reloadData] 在我的cellForItemAtIndexPath中,我有以下代码: - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtI

我整个下午都在这里,我想不出来,所以你的帮助太棒了!我有一个自定义的UICollectionViewCell,我用动态创建的图像填充它。图像的路径存储在Parse中,查询完成后,我调用[self.collectionView reloadData]

在我的cellForItemAtIndexPath中,我有以下代码:

- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {

MovieCollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:reuseIdentifier forIndexPath:indexPath];
// Configure the cell
NSSortDescriptor *sort = [NSSortDescriptor sortDescriptorWithKey:@"original_title" ascending:YES];
[self.moviesforWatchlist sortUsingDescriptors:[NSArray arrayWithObjects:sort, nil]];
cell.userInteractionEnabled = YES;
UIActivityIndicatorView *spinner = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhite];
[cell addSubview:spinner];

NSDictionary *movie = self.moviesforWatchlist[indexPath.row];
NSString *moviePosterPath = movie[@"poster_path"];
NSString *posterURL = [NSString stringWithFormat:@"http://image.tmdb.org/t/p/w342%@", moviePosterPath];
NSURL *posterImage = [NSURL URLWithString:posterURL];
UIImage *cachedImage = [self.imageCache objectForKey:posterImage];

if (cachedImage) {
    cell.imageView.image = cachedImage;
}
else if (cell.imageView.image == nil) {
    cell.imageView.image = [UIImage imageNamed:@"default_collectionviewcell.jpeg"];
    dispatch_queue_t downloadQueue = dispatch_queue_create("get image data", NULL);
    dispatch_async(downloadQueue, ^{
        [spinner startAnimating];
        NSData *imageData = [NSData dataWithContentsOfURL:posterImage];
        UIImage *image = [UIImage imageWithData:imageData];
        dispatch_async(dispatch_get_main_queue(), ^{
            [spinner stopAnimating];
            MovieCollectionViewCell *updateCell = (id)[collectionView cellForItemAtIndexPath:indexPath];
            if (updateCell) {
                updateCell.imageView.image = image;
                [updateCell reloadInputViews];
                [self.collectionView reloadItemsAtIndexPaths:[self.collectionView indexPathsForVisibleItems]];
         }
        });
        [self.imageCache setObject:image forKey:posterImage];
    });
    }
[self.collectionView reloadItemsAtIndexPaths:[self.collectionView indexPathsForVisibleItems]];
return cell;
}
我这样调用查询方法:

-(void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];
    [self getWatchlistData];
    [self.collectionView reloadData];
} 
这会导致图像闪烁,直到图像加载到UICollectionViewCells。我希望在我的collectionviewcell中显示的图像按字母顺序排列,因此我正在对保存路径的数组进行排序,在cellforitemsatindexpath中,这是导致图像闪烁的原因吗?还是别的什么?非常感谢你的帮助

尝试使用


我会改变很多事情:

我不会在CellForItemSatineXPath中对数组进行排序。当每个单元格都显示在屏幕上时,就会调用该方法,所以在不必要时,您可能会多次使用该方法。如果您的数据在创建的一个单元格和下一个单元格之间发生变化,则重新排序可能会打乱collectionView Indexath.row与数组索引之间的链接。我会在填充数组时对其进行排序,可能是在ViewWillDisplay或getWatchlistData方法中。如果数据在此之后发生更改,请使用其他一些collectionView委托/数据源方法来处理插入/删除/移动。但我不认为这是造成图像闪烁的原因

在发回主队列的代码中,调用cellForItemAtIndexPath方法,更新单元格映像并调用ReloadInputView,这可能会以某种方式重新配置单元格。但是,然后为所有可见的单元格调用ReloadItemSatinDexpath。这将导致collectionView为每个可见项重新调用cellForItemAtIndexPath数据源方法,从而从缓存中重新加载每个可见项的图像。我想这就是你闪烁的原因。我只需将下载的图像保存到缓存中,然后为受影响的indexPath调用reloadItemsAtIndexPaths。将调用cellForRowAtIndexPath数据源方法,并将从缓存中恢复图像并将其添加到新单元格中

同样,我认为cellForItemAtIndexPath末尾的重载ItemSatinDexpath是多余的,可能会导致闪烁

我认为您面临一些单元重用问题的风险-例如,您将微调器添加到每个单元。但是,出列的单元格可能以前已经显示过,因此已经有一个微调器,尽管它已停止,因此可能已隐藏。如果你经常来回滚动,你可能会得到一个有很多微调器的单元格,这会浪费内存。在将微调器添加为子视图之前,我会给它一个标记,然后使用viewWithTag确定是否已将微调器添加到已退出队列的单元格中。如果已添加,请将其删除。并且仅在必要时添加微调器,即在if…image==nil子句中

可能不太可能,但如果出列的单元格具有默认图像,则cell.imageView.image!=nil,并且正在为尚未缓存映像的单元格重新使用,因此cachedImage==nil,则不会执行任何分派方法,因此将永远不会下载映像


抱歉,如果这有点重,但我希望它有用。

我也有同样的问题,任何图像下载后都会弹出视图。我将在前面重新加载该单元格,因此它将调用collectionview的一些委托方法。所以我删除了它,并为重新加载单元格创建了一个单独的方法。现在,当任何新映像重新加载时,我调用此方法,而不是重新加载CellForIndeXPath:。在自定义方法中,只需从cellForItemAtIndexPath复制粘贴代码:。在自定义方法中指定单元格。 CollectionPhotoItem单元格=CollectionPhotoItem[self.collection cellForItemAtIndexPath:indexPath]


就这样。它将显示您的手机,无需任何轻弹。谢谢。

不用担心!我真的很感谢你的反馈。我刚刚开始学习Objective-C、iOS开发和编程,所以这些答案非常棒。我知道我做错了什么,但要让它正常工作还是要靠我自己。关于这个。。。我想它现在起作用了!我正在对数组进行排序,当它填充到getWatchListData方法中时,这似乎产生了很大的不同。基本上我做了你所有的建议。唯一的问题是,在第一次加载时,有时单元格中填充了错误的图像。你知道我该如何解决这个问题吗?只有几个要点:首先,检查你的缓存是否正确填充。在上一次运行中,它可能被错误地填充,即使您的代码现在可能没有问题。其次,要注意电池重复使用的问题,尤其是当你在列表中滚动时看到相同的图像时。我发现NSLog和断点非常有用 ul对追踪此类问题表示感谢。
[[DLImageLoader sharedInstance] displayImageFromUrl:@"image_url_here"
                                      imageView:@"UIImageView here"];

[[DLImageLoader sharedInstance] loadImageFromUrl:@"image_url_here"
                                   completed:^(NSError *error, UIImage *image) {
                                        if (error == nil) {
                                            // if we have no any errors
                                        } else {
                                            // if we got an error when load an image
                                        }
                                   }];