iOS 开发IT梦之队iOS系统框架

Photos中常用类(获取展示功能相关)简介

2016-05-18  本文已影响1402人  nuclear

简介

Photos framework是iOS8苹果提供的新的图片框架,能直接获取图片和视频,包括iCloud上面的图库。使用这个框架可以获取assets来展示和回放,编辑图片或者视频内容,或者使用系统相册、时刻、和分享到iCloud的相册来进行相关操作,本文侧重相片的获取与保存。
demo地址在这里

新特性与一些概念

framework中的类

PHAdjustmentData

当修改了一个asset后,Photos会将PHAdjustmentData对象和修改过的图片或者视频数据一起保存起来,你可以通过这个对象提供的一些数据来修改已经保存的编辑。

当需要调整data的时候,调用

- (PHContentEditingInputRequestID)requestContentEditingInputWithOptions:(PHContentEditingInputRequestOptions *)options
                                                      completionHandler:(void (^)(PHContentEditingInput *contentEditingInput, NSDictionary *info))completionHandler

初始化方法:

/**
 *  用于标记特定的修改数据,使用formatIndentifier和formatVersion指定唯一的adjustment,
 *  data存储用于回滚到之前状态的数据,也就是当前图片的修改数据,以便于在这个基础上继续进行修改
 *
 *  @param formatIndentifier 用于标记 adjustment data
 *  @param formatVersion     version number for adjustment data
 *  @param data              包含了重新修改需要的数据
 *
 */

- (instanceType)initWithForamtIndentifier:(NSString *)formatIndentifier
                            formatVersion:(NSString *)formatVersion
                                     data:(NSData *)data;

PHAssetChangeRequest

在图库中使用PHAssetChangeRequest对象来创建,修改,删除PHAsset对象。

可以使用适当的类方法来实现增加删除修改asset的目的:

/**
 *  删除给定的assets
 *
 *  @param assets 包含需要删除的asset数组
 */
+ (void)deleteAssets:(id<NSFastEnumeration>)assets;


/**
 *  修改给定的PHAsset对象
 *
 *  在修改之前使用 'canPerformEditOperation:' 方法判断asset是否允许修改
 *  在photo library change block中创建修改请求后,设置正确的修改请求属性。
 *
 *  @param asset 待修改的asset
 */
+ (instancetype)changeRequestForAsset:(PHAsset *)asset;

PHFetchOptions

当你使用没方法获取PHAsset(图片和视频),PHCollection(相册类型),PHAssetCollection(相册)的实体(相当于包含多个数据的模型)使用PHFetchOptions对象指定操作,例如获取的实体的排列属性等。

调用PHFetchRequest类方法创建一个包含fetch请求的对象。

这个类包含了两个属性:predicatesortDescriptors

specifies which properties to select results by and that also specifies any constraints on selection.

用于指定返回的结果和指定条件

示例:

PHFetchOperation *fetchOptions = [PHFetchOption new];
fetchOperations.predicate = [NSPredicate predicateWithFormat:
      @"(mediaSubtype & %d) != 0 || (mediaSubtype & %d) != 0",
      PHAssetMediaSubtypePhotoPanorama,PHAssetMediaSubtypeVideoHightFrameRate];

PHFetchResult *result = [PHAsset fetchAssetWithOptions:fetchOptions];

用一个例子实现以时间顺序倒序(刚拍摄的照片放在前头排列获取图片的功能:

PHFetchOption *option = [PHFetchOption new];
option.sourtDescriptors = @[NSSortDescriptors sortDescriptiorWithKey:@"creationDate" ascending:NO];
PHFetchResult *result = [PHAsset fetchAssetsWithOptions:option];

其他几个属性:

//用于确定app是否接收到了具体的改变信息。
@property(nonatomic, assign) BOOL wantsIncrementalChangeDetails

/**
 *限制检索获取得到的photo实体的最小数量,当实体数量十分巨大时,作用显著,
 *例如,用'PHAsset'的'fetchAssetsWithOptions:'方法获取最近拍摄的照片等。
 */
@property(nonatomic, assign, readwrite) NSUInteger fetchLimit

//检索结果是否包含连拍图片,如果是NO,只显示用户选取的那种图片,如果为YES,
@property(nonatomic, assign) BOOL includeAllBurstAssets

//顾名思义,是否检索隐藏的图片
@property(nonatomic, assign) BOOL includeHiddenAssets

/**
 *包含的数据类型:
 *PHAssetSourceTypeUserLibrary    
 *PHAssetSourceTypeCloudShared
 *PHAssetSourceTypeiTunesSynced 
 */
@property(nonatomic, assign) PHAssetSourceType includeAssetSourceTypes

PHImageRequestOption

PHImageRequestOption 用于配置从PHImageManager中获取asset的请求。
常用的一些属性和方法有:

/**
 *  @discuss 如果是NO,表示为异步操作,从manager中请求图片时,
 *  'reqeustImageForAssets:targetSize:options:resultHandler'方法会立即返回,
 *  建议在后台只在后台线程中执行同步请求
 */
@property (nonatomic, assign) BOOL synchronous;

/**
  *typedef : NSInteger {
     PHImageRequestOptionsDeliveryModeOpportunistic = 0,
     PHImageRequestOptionsDeliveryModeHighQualityFormat = 1,
     PHImageRequestOptionsDeliveryModeFastFormat = 2,
  } PHImageRequestOptionsDeliveryMode;
 
  *@PHImageRequestOptionsDeliveryModeOpportunistic:
    自动返回一个或多个结果,来平衡图片的质量和响应性,它会多次调用
    resutltHandler:'requestImageForAssets:targetSize:options:resultHandler'.
    它首先会先调用一次'resutltHandler'返回清晰度低的图片作为临时显示图片,
    等到能获取到高清晰度的图片时再次调用'resutltHandler'返回高质量图片。
 
    note:如果'synchronous'是NO那么该属性无效
 
  *@PHImageRequestOptionsDeliveryModeHighQualityFormat
    只返回高分辨率的图片。具有较高的优先权

  *@PHImageRequestOptionsDeliveryModeFastFormat
    快速返回结果,可能会牺牲图片质量。
 */
@property (nonatomic, assign) PHImageRequestOptionsDeliveryMode deliveryMode;

/**
 *  a mode that specifies how to resize the reuqested image
 */
@property(nonatomic, assign) PHImageRequestOptionsResizeMode resizeMode;

从iCloud中下载照片

/**
 *  能否从iCloud中下载图片,
    YES,本地也没有保存此图片,从iCloud上下载,用'progressHandler'这个block获取下载进度;
    NO,同时本地也没有图片,'progressHander'中的info[PHImageReustIsInCloudKey]返回值会表示不能下载
 */
@property(nonatomic, assign, getter=isNetworkAccessAllowed) BOOL networkAccessAllowed;

/**
  下载进度block,在多条线程中执行操作,刷新UI时需要回到主线程  
  */
typedef void (^ PHAssetImageProgressHandler)(double progress, NSError *error, BOOL *stop, NSDictionary *info);

@property(nonatomic, copy) PHAssetImageProgressHandler progressHandler

PHFetchResult

PHFetchRequest是有序的photo实体对象的容器,包含通过给定的检索条件返回的asset,相册,一个相册类型中的所有相册列表(例如,smart album类型下的所有相册,它是有序的),在PHAsset,PHCollection,PHAssetcollection,PHCollectionList这几个类中都包含有相应的类方法包含对应信息的PHFetchRequest对象,例如:

/**
 *  @param mediaType 
 *     aaset类型,包含有:
 *       PHAssetMediaTypeUnknown = 0,
 *       PHAssetMediaTypeImage,
 *       PHAssetMediaTypeVideo,
 *       PHAssetMediaTypeAudio,
 *
 *  @param options   检索操作
 *
 *  @return 带有符合条件的PHAsset对象集合的PHFetchRequest对象
 */
+(PHFetchResult<PHAsset *> *)fetchAssetsWithMeidaType:(PHAssetMediaType)mediaType
                                              options:(PHFetchOptions *)options
//Retrieves collections from the root of the photo library’s hierarchy of user-created albums and folders.
+(PHFetchResult<PHCollection *> *)fetchTopLevelUserCollectionsWithOption:(PHFetchOptions *)options;
/**
 *  获取自定条件的相册
 *
 *  @param type    相册类型:
         PHAssetCollectionTypeAlbum
         PHAssetCollectionTypeSmartAlbum
         PHAssetCollectionTypeMoment
 
 *  @param subtype 相对于相册类型更具体些的相片类型,如全景,照片流等
 
 *  @param options 检索条件
 *
 *  @return 符合条件的相册
 */
+(PHFetchResult<PHAssetCollection *> *)fetchAssetColletcionsWithType:(PHAssetCollectionType)type
                                                             subtype:(PHAssetCollectionSubtype)subtype
                                                             options:(PHFetchOptions *)options;
+(PHFetchResult<PHCollectionList *> *)fetchCollectionListsWithType:(PHCollectionListType)collectionListType
                                                            subtype:(PHCollectionListSubtype)subtype
                                                            options:(PHFetchOptions *)options

PHFetchRequest虽然包含了符合条件的photo实体的集合,与NSArray不同的是它会动态改变包含的内容,在处理大量的asset的时候效率更高些,实现的效果也好点

常用属性与方法

//是否包含给定的对象
- (BOOL)containsObject:(ObjectType)anObject

//包含的photo实体个数
@property(readonly) NSUInteger count

//指定类型的asset数量 
- (NSUInteger)countOfAssetsWithMediaType:(PHAssetMediaType)mediaType

PHImageManager

PHImageManager有一个单例方法,同时也提供了用于获取全尺寸图片,图片缩略图等方法.

获取图片:

/**
 *  会多次调用'resultHandler',第一次调用,返回的图片清晰度较低,
 *  当高清晰度图片可以获取时,会再次调用,如果高质量的图片在缓存汇中,只调用一次'resultHandler'。
 *  这个方法默认是异步的,当从后台线程调用这个方法时,需要将options的'synchronous'设为YES.
 *
 *  @param asset         保存图片信息的asset
 *  @param targetSize    返回的图片尺寸
 *  @param contentMode   返回的图片显示模式
 *  @param options       image request option
 *  @param resultHandler 返回的内容
 *
 *  @return 请求标示,用于取消请求*/
- (PHImageRequestID)requestImageForAsset:(PHAsset *)asset
                              targetSize:(CGSize)targetSize
                             contentMode:(PHImageContentMode)contentMode
                                 options:(PHImageRequestOptions *)options
                           resultHandler:(void (^)(UIImage *result, NSDictionary *info))resultHandler;

/**
 *  请求全尺寸的图片,只执行一次'resultHandler',
 *  如果options的'version'被设置为'PHImageRequestOptionsVersionCurrent,'
 *  返回在这个asset上发生的任何编辑后的imageData,如果不是的话,返回最原始版本的图片
 *
 *  @param asset         保存图片信息的asset
 *  @param options       image request option
 *  @param resultHandler 返回的内容
 *
 *  @return 请求标示,用于取消请求
 */
- (PHImageRequestID)requestImageDataForAsset:(PHAsset *)asset
                                     options:(PHImageRequestOptions *)options
                               resultHandler:(void (^)(NSData *imageData, NSString *dataUTI, UIImageOrientation orientation, NSDictionary *info))resultHandler;

取消请求:

- (void)cancelImageRequest:(PHImageRequestID)requestID

PHCachingImageManager

PHCachingImageManager是PHImageManager的子类,如果相册中有大量的图片,而你的需求是要快速的获取这些图片的缩略图和大图数据用于展示,这个时候可以用PHCachingImageManager来实现,它具有缓存机制可以快速获取一个图册的缩略图,或者在后台请求全尺寸图片以便于快速展示。

开始缓存图片:

/**
 *  @discuss 当调用这个方法的时候,cacaingManager开始在获取你所需要的数据,
 *  同时在后台生成缩略图,之后可以使用'requestImagesFromAssets:targetSize:contentMode:resultHandler:'
 *  方法从缓存中请求数据。
 *  Photos会按照给定的尺寸,显示模式返回图片,缓存中的图片尺寸是固定的
 *
 *  @param assets      需要缓存的assets
 *  @param targetSize  图片尺寸
 *  @param contentMode 显示模式
 *  @param options     请求操作
 */
- (void)startCachingImagesForAssets:(NSArray *)assets
                         targetSize:(CGSize)targetSize
                        contentMode:(PHImageContentMode)contentMode
                            options:(PHImageRequestOptions *)options;

取消图片缓存:

/**
 *  当使用collectionView展示图片缩略图的时候,如果需要改变尺寸大小的时候,
 *  就需要将缓存中的旧图片删除重新缓存。
 *
 *  @param assets      需要缓存的assets
 *  @param targetSize  图片尺寸
 *  @param contentMode 显示模式
 *  @param options     请求操作
 */
- (void)stopCachingImagesForAssets:(NSArray *)assets
                        targetSize:(CGSize)targetSize
                       contentMode:(PHImageContentMode)contentMode
                           options:(PHImageRequestOptions *)options;

PHPhotoLibrary

PHPhotoLibrary可以看成是一个用户图库,包含了一些的图片和相册,同时包含本地的和iCloud中的资源。当Photos app发生图片的修改、增加、删除等改变时,使用PHPhotoLibrary来做一些刷新UI,保存数据等响应动作,同时也可以注册观察者(使用registerChangeObserver方法),当Photos app内容发生改变的时,会触发代理方法photoLibraryDidChange

使用PHPhotoLibrary响应图库改变

Photos中的PHAsset,PHAssetCollection等是不可变对象,因此要改变当前这些类型对象的时候就需要使用photo library实现改变。

请求改变数据需要用到PHAssetChangeRequest,PHAssetcCollectionChangeRequest,PHCollectionListChangeRequest

使用步骤:

1、创建实体

每个change request类都提供了用于创建响应的实体类的方法:
creationRequestForAssetCollectionWithTitle:创建了一个asset Collection

如果要添加一个新的asset到collection中,需要用到change request提供的PHObjectPlaceholder对象。在change block结束之后,使用placeholder对象提供的localIdentifier属性获取创建好的asset对象。

2、删除实体

例如:deleCollectionLists用于删除collection list

3、修改实体

changeRqeustForAsset创建了一个可用于修改的asset的change request

下面代码实现往相册中添加新图片的功能:

- (void)addNewAssetWithImge:(UIImage *)image toAlbum:(PHAssetCollection *)album {
    
    [[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{
        
        PHAssetChangeRequest *assetChange = [PHAssetChangeRequest creationRequestForAssetFromImage:image];
        
        PHAssetCollectionChangeRequest *collectionChange = [PHAssetCollectionChangeRequest changeRequestForAssetCollection:album];
        
        PHObjectPlaceholder *placeholder = [assetChange placeholderForCreatedAsset];
        
        [collectionChange addAssets:@[placeholder]];
        
    } completionHandler:^(BOOL success, NSError * _Nullable error) {
       NSLog(@"Finished adding asset. %@", (success ? @"Success" : error));
    }];
}

note:For each call to the performChanges:completionHandler: or performChangesAndWait:error: method, iOS shows an alert asking the user for permission to edit the contents of the photo library.

注册观察者

PHPhotoLibraryChangeObserver在系统图库发生变化的时候就会通知指定的观察者,只要是使用了Photos framework实现的改变,都会触发观察者的方法。
registerChangeObserver:方法指定一名观察者,当系统图库发生改变,会触发观察者的指定方法,这个方法在PHPhotoLibraryChangeObserver协议中:- (void)photoLibraryDidChange:(PHChange *)changeInfo ;

PHCollection

PHCollection是一个抽象类,不允许直接使用它的实例对象,而是使用它的两个子类:PHAssetCollection,PHCollectionList
PHAssetCollection 包含了带有图片或者视频信息PHAsst对象,PHCollectionList可以看做是一个文件夹,里面存放多个相册或者是在年度相册中的所有时刻的照片。

获取图片集合:

//用特定的操作从collection list中获取collection集合
+ (PHFetchResult<PHCollection *>)fetchCollectionsInCollectionList:(PHCollectionList *)collectionList options:(PHFetchOptions *)options

//获取所有用户创建的相册或者文件夹。
+ (PHFetchResult<PHCollection *> *)fetchTopLevelUserCollectionWithOptions:(PHFetchOptions *)options;

PHAssetCollection

一个PHAssetCollection代表一个相册,可能包含图片和视频,例如:时间相册,我的照片流,自拍。

在Photos framework中不能直接获取collection中的内容,通过fetchAssetsInAssetCollecton:options:获取到包含PHAsset集合的PHFecthReult对象,之后用fetchResult提供的方法取出图片或者视频。

获取asset collection 的方法有许多种:

/**
 *  @param type    相册类型:
         PHAssetCollectionSubtypeAlbumRegular
         Photos APP中创建的相册
         
         PHAssetCollectionSubtypeAlbumSyncedEvent
         从iPhoto中同步的事件相册
         
         PHAssetCollectionSubtypeAlbumSyncedFaces   
         从iPhoto中同步的包含人脸的相册
         
         PHAssetCollectionSubtypeAlbumSyncedAlbum
         从iPhoto同步的普通相册
         
         PHAssetCollectionSubtypeAlbumImported
         从其他设备导入的相册
         
         PHAssetCollectionSubtypeAlbumCloudShared
         分享到iCloud的照片流相册
         
         PHAssetCollectionSubtypeAlbumMyPhotoStream
         用户个人的iCloud照片流
         
         PHAssetCollectionSubtypeSmartAlbumGeneric
         没有特定类型的只能相册
         
         PHAssetCollectionSubtypeSmartAlbumPanoramas
         全景图片相册
         
         PHAssetCollectionSubtypeSmartAlbumVideos
         视频相册
         
         PHAssetCollectionSubtypeSmartAlbumFavorites
         个人收藏
         
         PHAssetCollectionSubtypeSmartAlbumTimelapses
         延时摄影相册
         
         PHAssetCollectionSubtypeSmartAlbumAllHidden
         隐藏的图片相册
         
         PHAssetCollectionSubtypeSmartAlbumRecentlyAdded
         最近添加的图片
         
         PHAssetCollectionSubtypeSmartAlbumBursts
         连拍相册
         
         PHAssetCollectionSubtypeSmartAlbumSlomoVideos
         慢动作视频相册
         
         PHAssetCollectionSubtypeSmartAlbumUserLibrary
         在本地存在的相册(不包含icloud中的相册)
         
         PHAssetCollectionSubtypeSmartAlbumSelfPortraits
         自拍
         
         PHAssetCollectionSubtypeSmartAlbumScreenshots
         截屏
         
         PHAssetCollectionSubtypeAny
         获取所有类型的相册
 
 *  @param options 筛选操作
 *
 *  @return 包含符合条件的相册的fetch result
 */
+ (PHFetchResult<PHAssetCollection *> *)fetchAssetCollectionsWithType:(PHAssetCollectionType)type subtype:(PHAssetCollectionSubtype)subtype options:(nullable PHFetchOptions *)options;


/**
 *  获取符合特定类型同时包含指定asset的相册集合
 *
 *  @param asset   给定的sset
 *  @param type    指定相册类型
 *  @param options 获取操作
 *
 */
+ (PHFetchResult<PHAssetCollection *> *)fetchAssetCollectionsContainingAsset:(PHAsset *)asset withType:(PHAssetCollectionType)type options:(PHFetchOptions *)options;

PHCollectionList

PHCollectionList包含了更高级别的asset集合,可嵌套PHAssetCollection
和自身类型,还支持多重嵌套,例如获取时刻相册和时刻相册中年度照片等。

获取collection list的几种方法:


+ (PHFetchResult<PHCollectionList *>)fetchCollectionListsContainingCollection:(PHCollection *)collection options:(PHFetchOptions *)options;
+ (PHFetchResult<PHCollectionList *> *)fetchCollectionListsContainingCollection:(PHCollection *)collection options:(nullable PHFetchOptions *)options;
+ (PHFetchResult<PHCollectionList *> *)fetchCollectionListsWithLocalIdentifiers:(NSArray<NSString *> *)identifiers options:(nullable PHFetchOptions *)options;
+ (PHFetchResult<PHCollectionList *> *)fetchCollectionListsWithType:(PHCollectionListType)collectionListType subtype:(PHCollectionListSubtype)subtype options:(nullable PHFetchOptions *)options;

+ (PHFetchResult<PHCollectionList *> *)fetchMomentListsWithSubtype:(PHCollectionListSubtype)momentListSubtype containingMoment:(PHAssetCollection *)moment options:(nullable PHFetchOptions *)options;
+ (PHFetchResult<PHCollectionList *> *)fetchMomentListsWithSubtype:(PHCollectionListSubtype)momentListSubtype options:(nullable PHFetchOptions *)options;

PHAsset

PHAsset代表一个视频或者图片资源,当需要展示或者修改Photos app中的图片时需要先获取asset,asset是不可改变的并且只保存了所代表的视频或者图片的metadata。

获取PHAsset的几种方法:

//从asset collection中获取符合条件的asset集合
+ (PHFetchResult <PHAsset *> *)fetchAssetsInAssetCollection:(PHAssetCollection *)assetCollection options:(PHFetchOptions *)options

/**
 *   默认返回所有类型的asset,如果要给asset添加更多的类型限定,可以在options的filter predicate中设置。
 *  @param mediaType :
         PHAssetMediaTypeUnknown
         未知类型
 
         PHAssetMediaTypeImage
         静态图片
         
         PHAssetMediaTypeVideo
         视频
         
         PHAssetMediaTypeAudio
         音频

注: PHMediaSubtype:
   
    PHAssetMediaSubtypeNone               = 0,
    
    // Photo subtypes
    PHAssetMediaSubtypePhotoPanorama      = (1UL << 0),
    PHAssetMediaSubtypePhotoHDR           = (1UL << 1),
    PHAssetMediaSubtypePhotoScreenshot NS_AVAILABLE_IOS(9_0) = (1UL << 2),
    PHAssetMediaSubtypePhotoLive NS_AVAILABLE_IOS(9_1) = (1UL << 3),

    
    // Video subtypes
    PHAssetMediaSubtypeVideoStreamed      = (1UL << 16),
    PHAssetMediaSubtypeVideoHighFrameRate = (1UL << 17),
    PHAssetMediaSubtypeVideoTimelapse     = (1UL << 18),
 */
+ (PHFetchResult <PHAsset *>  *_Nullable)fetchAssetsWithMediaType:(PHAssetMediaType)mediaType options:(PHFetchOptions *_Nullable)options;

+ (PHFetchResult *<PHAsset *> *)fetchAssetsWithLocalIndentifiers:(NSArray <NSString *>)identifier options:(PHFetchOptions *)options;

/**
 *  获取key asset,每一个collection都至少有一个key asset,每个不同类型的collection用于定义key asset的方式也不同,有的collection中只有一个key asset,有的含有多个。
 *  例如在相机胶卷中,最近拍摄的图片或者视频就是key asset
 */
+ (PHFetchResult <PHAsset *>)fetchKeyAssetsInAssetCollection:(PHAssetCollection *)collection options:(PHFetchOptions *)options;

/**
 *  获取所有的符合条件的asset,默认条件下,不包含通过iTunes同步过来的和存储在iCloud中的图片。
 *  更改此条件,配置options的'includeAssetSourceType'属性来实现。
 */
+ (PHFetchResult <PHAsset *> *)fetchAssetsWithOptions:(PHFetchOptions *)options;

//获取连拍照片
+ (PHFetchResult <PHAsset *>)fetchAssetWithBurstIdentifier(NSString *)burstIdentifier options:(PHFetchOptions *)options;
上一篇下一篇

猜你喜欢

热点阅读