PHPhotoLibrary(译)
PHPhotoLibrary
管理访问和更改用户的照片库的单例对象
PHAsset 代表一张图片或者一个视频(文中提到的资源).
PHAssetCollection 表示一个相册或者一个时刻,或者是一个智能相册(系统提供的特定的一系列相册,例如:最近删除,视频列表,收藏等等. 文中提到的资源集).
PHCollectionList 表示一组相册, 例如照片中的"年度"(里面包含按地区分类的相册), 一般使用AssetCollection
就行, 跟PHAssetCollection
差不多.
概述
PHPhotoLibrary
的单例对象sharedPhotoLibrary
代表着Photo App
(照片)
管理的资源的集合, 包括在本地储存的资源和iCloud上的资源(如果有的话). 你可以使用这个对象来执行你对PhotoLibrary
的操作. 举个栗子: 编辑一个资源的元数据或者它的内容, 增加新的资源, 或者对资源集内部资源进行整理. 当PhotoLibrary
中有资源或者资源集的内容或者元数据发生变化时会发送一个消息, 你可以通过sharedPhotoLibrary
注册一个观察者并获取这个消息. sharedPhotoLibrary
也可以用来验证当前App是否能访问PhotoLibrary
.
对 PhotoLibrary 的更改
PHAsset
, PHAssetCollection
,PHCollectionList
的实例对象都是不可变的. 因此, 为了修改这些对象所代表的资源或者资源集, 你应该使用sharedPhotoLibrary
来执行一个包含修改内容的block. 在这个block中, 你需要创建一个修改请求对象. 创建好之后, 将这个包含修改请求的block作为参数提交到performChanges:completionHandler:
或performChangesAndWait:error:
中. 当sharedPhotoLibrary
执行了这个block之后, 会调用completion handler
.
操作请求类PHAssetChangeRequest
PHAssetCollectionChangeRequest
PHCollectionListChangeRequest
分别与资源, 资源集对应.通过这些类,我们可以执行我们需要的操作:
-
增
每个Request
类都提供了一些方法来创建一个新的资源或者资源集.比如creationRequestForAssetCollectionWithTitle :
方法可以创建一个新的资源集.
想要在包含Request
的block中引用新创建的资源或资源集, 例如添加一个新的资源到一个资源集, 可以用到PHObjectPlaceholder对象. 所有的Request
类都提供了获取这个对象的方法. 当block完成之后, 可以通过PHObjectPlaceholder
对象的'localIdentifier'属性找到创建的资源或资源集的实体 . -
删
每个修改类都提供了方法来删除一个或者多个资源, 例如用deleteCollectionLists :
可以删除collection lists
-
改
如果想要修改一个已存在的资源或者资源集, 就先要创建PHAsset, PHAssetCollection, 或 PHCollectionList
的实例对象. 举个栗子:changeRequestForAsset:
方法创建了一个可以修改资源的request
. 创建好请求之后, 通过request
的某些属性或者调用它的方法来修改这个请求所对应资源. 如, 将一个资源设置为favorite
, 更改request
的favorite
属性就可以了; 想在资源集中添加一个资源, 就调用资源集对应的request
的addAssets :
方法.
如果有多个修改请求的话, 可以将他们放在一个block中, 用一次原子性更新(single atomic update atomic没有想到很好的词 请指教)来完成. 下面的代码展示了如何创建一个Asset
并将其放入一个AssetCollection
(相册).
+ (void)addNewAssetWithImage:(UIImage *)image toAlbum:(PHAssetCollection *)album onSuccess:(void(^)(NSString *ImageId))onSuccess onError: (void(^)(NSError * error)) onError
{
[[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{
// Request creating an asset from the image.
PHAssetChangeRequest *createAssetRequest = [PHAssetChangeRequest creationRequestForAssetFromImage:image];
// Request editing the album.
PHAssetCollectionChangeRequest *albumChangeRequest = [PHAssetCollectionChangeRequest changeRequestForAssetCollection:album];
// Get a placeholder for the new asset and add it to the album editing request.
PHObjectPlaceholder * placeHolder = [createAssetRequest placeholderForCreatedAsset];
[albumChangeRequest addAssets:@[ placeHolder ]];
NSLog(@"%@",placeHolder.localIdentifier);
if (placeHolder) {
onSuccess(placeHolder.localIdentifier);
}
} completionHandler:^(BOOL success, NSError *error) {
NSLog(@"Finished adding asset. %@", (success ? @"Success" : error));
if (error) {
onError(error);
}
}];
}
注意:
当调用performChanges:completionHandler:
或performChangesAndWait:error:
方法时, 会弹出提示框询问用户是否允许编辑"照片"的内容(增删改之类). 如果在你的app中需要一次提交多个修改请求, 可以把它们放入一个block
中.
举个栗子, 一次性在相册中增加多张图片, 可以在上面的代码中通过creationRequestForAssetFromImage:
方法添加多个PHAssetChangeRequest
; 编辑多张照片也可以创建多个PHAssetChangeRequest
并设置每个request
contentEditingOutput
属性为相应的PHContentEditingOutput
对象.
观察发生的修改
通过registerChangeObserver :
方法注册一个观察者, 就可以知道photo library
发生改变了. 当你用了fetch
方法(如 fetchAssetsWithOptions :
)来获取assets
或collections
的时候, 照片会自动将这些获取到的assets
或collections
的改变告诉观察者. fetch
出来的assets
或collections
, 当它们有改变的时候. 例如, 添加或, 移除, 或者重新排列collections
中的内容, 也会告诉观察者. 如果想要了解更多, 可以查看PHPhotoLibraryChangeObserver protocol.
一些方法
- 授权
// 获取授权状态
+ (PHAuthorizationStatus)authorizationStatus;
// 获取授权 block为用户的授权状态
+ (void)requestAuthorization:(void(^)(PHAuthorizationStatus status))handler;
- 操作
+ (PHPhotoLibrary *)sharedPhotoLibrary;
// 异步执行
- (void)performChanges:(dispatch_block_t)changeBlock completionHandler:(nullable void(^)(BOOL success, NSError *__nullable error))completionHandler;
// 同步执行
- (BOOL)performChangesAndWait:(dispatch_block_t)changeBlock error:(NSError *__autoreleasing *)error;
- 观察者
// 注册观察者
- (void)registerChangeObserver:(id<PHPhotoLibraryChangeObserver>)observer;
// 注销观察者
- (void)unregisterChangeObserver:(id<PHPhotoLibraryChangeObserver>)observer;