iOS PhotoKit 教程

Posted Xiejunyi12

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了iOS PhotoKit 教程相关的知识,希望对你有一定的参考价值。

Demo,简单实现了照片选择器的功能

PhotoKitDemo
欢迎给Star!!!

  • PHAsset: 代表照片库中的一个资源,跟 ALAsset 类似,通过 PHAsset 可以获取和保存资源
  • PHFetchOptions: 获取资源时的参数,可以传 nil,即使用系统默认值
  • PHAssetCollection: PHCollection 的子类,表示一个相册或者一个时刻,或者是一个「智能相册(系统提供的特定的一系列相册,例如:最近删除,视频列表,收藏等等,如下图所示)
  • PHFetchResult: 表示一系列的资源结果集合,也可以是相册的集合,从?PHCollection 的类方法中获得
  • PHImageManager: 用于处理资源的加载,加载图片的过程带有缓存处理,可以通过传入一个 PHImageRequestOptions 控制资源的输出尺寸等规格
  • PHImageRequestOptions: 如上面所说,控制加载图片时的一系列参数

常用的概念

PHCachingImageManager

提供检索或生成预览缩略图以及与Photos资源相关联的全尺寸图片或视频数据的方法,这些图片或视频数据针对批量预加载大量资产进行了优化。
为了在使用许多资产时快速运行,缓存图像管理器可以在后台准备资产图像,以便在以后请求单个图像时消除延迟。例如,当您希望使用照片或视频资源的缩略图填充集合视图或类似的用户界面时,请使用缓存图片管理器。
PHCachingImageManager类的许多关键功能由其超类PHImageManager定义。有关详细信息,请参阅PHImageManager。
要使用缓存图像管理器:

  1. 创建PHCachingImageManager实例。 (此步骤使用共享的PHImageManager实例替换。)
    使用PHAsset类方法获取您感兴趣的资产。
  2. 要为这些资产准备图像,请调用startCachingImages(for:targetSize:contentMode:options :)方法,使用目标大小,内容模式和计划在稍后为每个单独资产请求图像时使用的选项。
  3. 当您需要单个资产的图像时,请调用requestImage(for:targetSize:contentMode:options:resultHandler :)方法,并传递您在准备该资产时使用的相同参数。
  4. 如果您请求的图像在已准备好的图像中,则PHCachingImageManager对象立即返回该图像。否则,照片会根据需要准备图像,并将其缓存以供以后使用。

PHFetchResult

从照片提取方法返回的资源或集合的有序列表。
当您在PHAsset,PHCollection,PHAssetCollection和PHCollectionList类中使用类方法来检索对象时,Photos会在提取结果中提供生成的对象。您可以使用与NSArray类所使用的方法和约定相同的方式访问获取结果的内容。然而,与NSArray对象不同,PHFetchResult对象根据需要从Photos库动态加载其内容,即使在处理大量结果时也能提供最佳性能。
提取结果提供对其内容的线程安全访问。抓取后,抓取结果的计数值为常量,并且抓取结果中的所有对象保持相同的localIdentifier值。 (要获取更新的内容以获取,请使用共享的phphotoLibrary对象注册变更观察器。)
提取结果缓存其内容,在最近访问的索引周围保留一批对象。由于批处理之外的对象不再缓存,访问这些对象会导致重新获取这些对象。此过程可能会导致更改以前从这些对象读取的值。

PHFetchOptions

一组影响过滤,排序和管理结果的选项,当您提取资源或集合对象时,Photos会返回。
在PHAsset,PHCollection,PHAssetCollection和PHCollectionList类上使用类方法来获取资产或集合时,会生成包含所请求对象的PHFetchResult对象。 您指定的选项控制抓取结果的对象,包括这些对象在抓取结果中的排列方式,以及Google相册应如何通知您的应用抓取结果的更改。
照片仅支持谓词和sortDescriptors属性的一组受限制的键。 可用键的集合取决于您用来获取资源或集合的类。

核心代码

累了…

NSString *kXJYGridCollectionViewCell = @"XJYGridCollectionViewCell";

@interface XJYPhotoSelectorController ()<PHPhotoLibraryChangeObserver>

@property (nonatomic, strong) XJYCollectionViewFlowLayout *layout;
//抓取结果
@property (nonatomic, strong) PHFetchResult<PHAsset *> *fetchResult;

@property (nonatomic, strong) PHCachingImageManager *imageManager;

@property (nonatomic, strong) PHAssetCollection *assetCollection;

@property (nonatomic, assign) CGSize thumbnailSize;

@property (nonatomic, assign) CGRect previousPreheatRect;


@end

@implementation XJYPhotoSelectorController

#pragma mark Class Method

- (instancetype)init 
    self = [self initWithCollectionViewLayout:self.layout];
    return self;


- (instancetype)initWithCollectionViewLayout:(UICollectionViewLayout *)layout 
    if (self = [super initWithCollectionViewLayout:self.layout]) 

    
    return self;



#pragma mark View Life Cycle
- (void)viewDidLoad 
    [super viewDidLoad];
    self.view.backgroundColor = [UIColor whiteColor];
    self.previousPreheatRect = CGRectZero;
    [self resetCachedAssets];

    self.automaticallyAdjustsScrollViewInsets = YES;
    self.collectionView.backgroundColor = [UIColor whiteColor];



#pragma mark PhotoKit

    self.imageManager = [PHCachingImageManager defaultManager];

    [[PHPhotoLibrary sharedPhotoLibrary] registerChangeObserver:self];

    PHFetchOptions *allPhotosOptions = [[PHFetchOptions alloc] init];
    allPhotosOptions.sortDescriptors = @[[NSSortDescriptor sortDescriptorWithKey:@"creationDate" ascending:YES]];

    self.fetchResult = [PHAsset fetchAssetsWithOptions:allPhotosOptions];



#pragma mark Register Cell
    // Register cell classes
    [self.collectionView registerClass:[XJYGridCollectionViewCell class] forCellWithReuseIdentifier:kXJYGridCollectionViewCell];

    //Scroll to End
    NSInteger section = [self.collectionView numberOfSections] - 1;
    NSInteger item = [self.collectionView numberOfItemsInSection:section] - 1;
    NSIndexPath *indexPath = [NSIndexPath indexPathForItem:item inSection:section];
    [self.collectionView scrollToItemAtIndexPath:indexPath atScrollPosition:(UICollectionViewScrollPositionBottom) animated:YES];




- (void)viewDidAppear:(BOOL)animated 
    [super viewDidAppear:animated];
    [self updateCachedAssets];




- (void)didReceiveMemoryWarning 
    [super didReceiveMemoryWarning];
    [[PHPhotoLibrary sharedPhotoLibrary] unregisterChangeObserver:self];


/*
#pragma mark - Navigation

// In a storyboard-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender 
    // Get the new view controller using [segue destinationViewController].
    // Pass the selected object to the new view controller.

*/
#define kScreen_Height [UIScreen mainScreen].bounds.size.height
#define kScreen_Width [UIScreen mainScreen].bounds.size.width

#pragma mark Getter

- (XJYCollectionViewFlowLayout *)layout 
    if (!_layout) 

        _layout = [[XJYCollectionViewFlowLayout alloc] init];
        _layout.itemSize = CGSizeMake((kScreen_Width-20)/4, (kScreen_Width-20)/4);
        _layout.minimumLineSpacing = 2.0;
        _layout.minimumInteritemSpacing = 2.0;
        _layout.scrollDirection = UICollectionViewScrollDirectionVertical;
        _layout.sectionInset = UIEdgeInsetsMake(5, 5, 5, 5);
    
    return _layout;


- (CGSize)thumbnailSize 
    CGFloat scale = [UIScreen mainScreen].scale;
    _thumbnailSize = CGSizeMake(scale * self.layout.itemSize.width, scale * self.layout.itemSize.height);
    return _thumbnailSize;


#pragma mark <UICollectionViewDataSource>

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



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


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



    //根据Index 获取asset
    PHAsset *asset = [self.fetchResult objectAtIndex:indexPath.item];

    //设置cell representedAssetIdentifier
    cell.representedAssetIdentifier = asset.localIdentifier;

    //imageManager 请求image
    [self.imageManager requestImageForAsset:asset targetSize:self.thumbnailSize contentMode:PHImageContentModeAspectFill options:nil resultHandler:^(UIImage * _Nullable result, NSDictionary * _Nullable info) 
        if ([cell.representedAssetIdentifier isEqualToString: asset.localIdentifier]) 
            cell.image = result;
        
    ];

    return cell;

以上是关于iOS PhotoKit 教程的主要内容,如果未能解决你的问题,请参考以下文章

photoKit不得不说的坑

iOS PhotoKit框架 详解

iOS 8、PhotoKit、PHAsset、唯一标识符

在 PhotoKit 中删除:您可以跳过“最近删除”吗?

[iOS] photoKit获取所有照片

iOS PhotoKit框架如何获取视频文件大小