IOS Photos 应用程序如何在一个屏幕上显示数百张照片?

Posted

技术标签:

【中文标题】IOS Photos 应用程序如何在一个屏幕上显示数百张照片?【英文标题】:How can IOS Photos app can show hundreds of photos in one screen? 【发布时间】:2014-10-10 10:57:08 【问题描述】:

我正在开发一个依赖于在屏幕上显示来自多个来源的大量照片的应用程序。

我想知道苹果如何在他们的照片应用程序中制作“照片拼贴”视图?有了这么多照片,我认为该应用程序应该在一次显示较少的照片(即使我以“缩略图大小”加载照片)时发出内存警告,但我可以看到当我缩放时它可以在一个屏幕上显示数百张照片出去。

我能想到的一种方法是,这些视图不是单张照片,而是实时从照片生成的单个“平铺”图像,因此该应用一次只显示 2-3 张照片。但这仍然需要大量的 CPU 功率和时间才能快速生成。我可以立即放大或缩小。

我想在我的应用程序中实现类似的功能,任何关于如何实现这一点的指导都会很棒。

感谢您的回答。

【问题讨论】:

如果缩略图那么小,为什么会占用太多内存? @DenizAdalar 因为照片太多。在我看来,加载“ALAsset”太慢了,无法实时加载那么多照片(每张照片都加载到单独的线程中)。 几天前我想实现这样的东西,在年视图中,我的收藏视图无法平滑滚动。 @CarouselMin 是的,这就是我的观点,我认为 photos.app 所做的事情与仅放置较小的图像不同 【参考方案1】:

我做了一些研究,发现ios8有一个很棒的新框架,叫做“照片框架”

此框架可让您轻松缓存图像、调用具有预定义大小的缩略图图像和加载项目。 (旧的 ALAsset 库只有一个“缩略图”大小,您必须调整自己的大小。)

在我的测试中,屏幕上满是 20x20 的照片(我的手机屏幕内容为 384 张图片),应用程序只占用 10mb 的内存,滚动时几乎没有闪烁。通过优化单元重新加载imo可以实现平滑滚动。

这是我用于将图像加载到 20x20 项目大小的 uicollectionview 中的代码:

@import Photos;
@interface MainViewController ()

@property (strong) PHFetchResult *assetsFetchResults;
@property (strong) PHCachingImageManager* imageManager;

@end

在 viewDidLoad 上:

- (void)viewDidLoad 
    [super viewDidLoad];

    self.imageManager = [[PHCachingImageManager alloc] init];

    CGFloat scale = [UIScreen mainScreen].scale;
    CGSize cellSize = ((UICollectionViewFlowLayout *)self.collectionViewLayout).itemSize;
    AssetGridThumbnailSize = CGSizeMake(cellSize.width * scale, cellSize.height * scale);

    [self.collectionView registerClass:[UICollectionViewCell class] forCellWithReuseIdentifier:reuseIdentifier];
    self.assetsFetchResults = [PHAsset fetchAssetsWithOptions:nil];
    // Do any additional setup after loading the view.

和集合视图数据源方法:

#pragma mark <UICollectionViewDataSource>

- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView 
    return 1;



- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section 
    return self.assetsFetchResults.count;


- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath 
    UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:reuseIdentifier forIndexPath:indexPath];

    [self.imageManager requestImageForAsset:self.assetsFetchResults[indexPath.item] 
                                 targetSize:CGSizeMake(20, 20) 
                                contentMode:PHImageContentModeAspectFill 
                                    options:nil resultHandler:^(UIImage *result, NSDictionary* info)

                                        UIImageView* imgView = (UIImageView*)[cell.contentView viewWithTag:999];
                                        if(!imgView) 
                                            imgView = [[UIImageView alloc] initWithFrame:[cell.contentView bounds]];
                                            imgView.tag = 999;
                                            [cell.contentView addSubview:imgView];
                                        
                                        imgView.image = result;
                                    ];
    // Configure the cell

    return cell;

就是这样!

【讨论】:

你能提供一个示例项目吗,我从苹果修改了照片代码,仅将集合视图项目大小更改为 20x20,我的 iPhone 4S 使用了 15.6MB 内存使用,滚动不是那光滑。 AssetGridThumbnailSize 是 40x40,因为 4S 的比例是 2,所以目标尺寸也是 40x40 而不是 20x20。您是如何通过优化单元重新加载实现仅 10MB 内存使用的? @CarouselMin 我也在 iphone4s 上进行测试,顺便说一句,这是项目:github.com/dreampowder/photosSample 我测试了这个项目,它的内存使用是10mb~11mb,比较好,只是图像有点模糊,把targetSize:CGSizeMake(20, 20)改为targetSize:CGSizeMake(40 , 40) 让照片清晰,但使用量高达11~12mb,滚动有点慢,总之比滚动时缓存一些照片的源代码要好。 是的,图像看起来很模糊,但请记住,您正在将 5-8 兆像素的图像缩小到 20x20 大小:) 我认为您没有使用 PHCachingImageManger 缓存任何图像。为了缓存图像,您需要在 PHCachingImageManager 上调用此方法,startCachingImagesForAssets(_:targetSize:contentMode:options:)【参考方案2】:

使用 PHCachingImageManager 的 Apple 示例要好得多,因为它还使用了预热文本,以便缓存正确的资源。请查看https://github.com/robovm/apple-ios-samples/blob/master/ExampleappusingPhotosframework/SamplePhotosApp/AAPLAssetGridViewController.m

【讨论】:

找不到这个链接! @Faizyy 给你

以上是关于IOS Photos 应用程序如何在一个屏幕上显示数百张照片?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 iOS 设备的外部屏幕上显示自定义内容

如何使用 Photos 框架从 iOS 上的相机胶卷中获取最新照片?

PHAsset,如何在应用重启后检索特定的 PHAsset 对象(ios8 Photos)

IOS5 中的本地通知 - 如何让它在屏幕上而不是在通知中心弹出?

如何像 iOS Photos 应用一样实现缩放*和*分页

如何在 iOS 屏幕上点击某个区域时隐藏 UIView 并使其显示