首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >高效处理UIImage在UICollectionView中的加载

高效处理UIImage在UICollectionView中的加载
EN

Stack Overflow用户
提问于 2014-08-26 15:20:07
回答 2查看 1.2K关注 0票数 2

在我的应用程序中,用户可以为他们的宠物拍照,或者其他什么,这将显示在集合视图中作为一个圆形的图片。如果没有显示默认照片,则使用cellForItemAtIndexPath检查用户生成的照片是否存在(该照片作为png文件存储在Documents目录中)。

发布:-当滚动UICollectionView时,图像加载将停止滚动UI的平滑性,因为图片将出现在屏幕上。

  • 如果你将图片从屏幕上滚动多次,应用程序会因为内存压力而崩溃。

问题:是否有一种有效的方法来加载图像并将其保存在内存中,而不必在图像第一次显示后继续加载?

我认为光栅化图像会有帮助,但看起来UI滚动和内存问题仍然存在。

以下是代码:

代码语言:javascript
复制
-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {

    static NSString *CellIdentifierPortrait = @"allPetCellsPortrait";

    AllPetsCell *cell = (AllPetsCell *)[collectionView dequeueReusableCellWithReuseIdentifier:CellIdentifierPortrait forIndexPath:indexPath];

    CGRect rect = CGRectMake(cell.petView.center.x, cell.petView.center.y, cell.petView.frame.size.width, cell.petView.frame.size.height);

    UIImageView *iv = [[UIImageView alloc] initWithFrame:rect];

    //set real image here
    NSString *petNameImage = [NSString stringWithFormat:@"%@.png", self.petNames[indexPath.section][indexPath.item]];
    NSString *filePath = [_ad documentsPathForFileName:petNameImage];
    BOOL fileExists = [[NSFileManager defaultManager] fileExistsAtPath:filePath];

    iv.image = nil;
        if (fileExists){

                [_allPetsCollectionView performBatchUpdates:^{
                    if (iv && fileExists) {

                      iv.image = [UIImage imageWithContentsOfFile:filePath];

                    }

                } completion:^(BOOL finished) {
                    //after

                }];
                //loadedImage = YES;

        [collectionView layoutIfNeeded];
        }//file exists
    else{

        iv.image = [UIImage imageNamed:[NSString stringWithFormat:@"%@", self.contents[indexPath.section][indexPath.item]]];

        [cell.petNameLabel setTextColor:[UIColor darkGrayColor]];//be aware of color over pictures
        shadow.shadowColor = [UIColor whiteColor];
    }
    cell.petView.clipsToBounds = YES;
    UIColor *color = MediumPastelGreenColor;

    if ([[NSString stringWithFormat:@"%@", self.contents[indexPath.section][indexPath.item]] isEqualToString:@"addpet.png"]) {
        color = MediumLightSkyBlueColor;
    }

    [cell.petView setBounds:rect forBorderColor:color];

    [cell.petView addSubview:iv];

    if (![[NSString stringWithFormat:@"%@", self.contents[indexPath.section][indexPath.item]] isEqualToString:@"addpet.png"])
    [iv addSubview:cell.petNameLabel];
    //TODO: optimize the cell by rasterizing it?
    if ([_contents count] > 4) {
        cell.layer.shouldRasterize = YES;
    }

    return cell;
}

下面是屏幕截图:

谢谢!

EN

回答 2

Stack Overflow用户

发布于 2015-03-22 16:15:26

将图像分配给集合视图单元格的imageView不需要任何性能问题。

这里有两个问题。

  1. 从集合视图的委托方法中获取内容(集合视图的数据源)。--这是造成延迟的原因.
  2. 您将一次又一次地添加保存图像的imageView。因此,每次显示单元格时,都会将保存新获取数据的新imageView作为subView添加到重用的单元格中(因为新的imageView覆盖旧的单元格,因为它们都具有相同的帧,因此您不会注意到这一点。而在同一时间,它会消耗掉记忆)。这是导致内存压力崩溃的原因.

溶液

  • 用于改进性能的

代码语言:javascript
复制
1. Fetch the image contents from your model class(if you are using one), or from you viewController's viewDidLoad() (**You should never fetch datasource from within the collection view's delegate method**). Perform the fetching process in the background queue as it wouldn't affect your UI in any manner.
2. Store the contents onto an array and fetch the contents only from the array to populate your collection view cells.

  • 避免内存崩溃的 只要您不使用自定义集合视图单元格,那么最好在每次单元格退出队列时,将所有子视图从收藏品查看单元格的内容视图中删除。

我希望这能解决你的问题:)

票数 1
EN

Stack Overflow用户

发布于 2014-09-02 15:04:53

我最近发现了NSCache,它是一个字典类型的对象,我可以将我的*已加载的图像*s存储到其中,并检查它们是否带有-cellForItemAtIndexPath方法。

为此,我更改了上面的代码,使用了将发送到主队列的自定义调度队列。当加载初始图像时,这仍然会导致滚动中出现轻微的停顿凸起,但之后从图像缓存中读取。还不完全理想,但我认为我正朝着正确的方向前进。

以下是代码:

代码语言:javascript
复制
if (fileExists){
        //DONE: implement NSCACHE and dispatch queue
        const char *petImageQ = "pet image";
        dispatch_queue_t petImageQueue = dispatch_queue_create( petImageQ, NULL);

        //check to see if image exsists in cache - if not add it.
        if ([_petImagesCache objectForKey:petNameImage] == nil) {

            dispatch_async(petImageQueue, ^{
                dispatch_async(dispatch_get_main_queue(), ^{

                    [collectionView performBatchUpdates:^{
                        iv.image = [UIImage imageWithContentsOfFile:filePath];

                    } completion:^(BOOL finished) {
                        //add to cache
                        [_petImagesCache setObject:iv.image forKey:petNameImage];
                    }];

                });

            });

        }
        else{
            //load from cache
            iv.image = [_petImagesCache objectForKey:petNameImage];
        }

我希望这能帮到你。请增加更多,以改善它!

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/25509508

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档