Photos 框架简介
- photos框架是ios8 之后退出来的一个专门处理图片和视频的框架. 通过这个框架开发者可以很容易方便的访问iphone 手机上Photos 这个应用.换句话说,你要访问操作iPhone 上的photos应用就使用Photos框架.
一.保存图片到[自定义相册]
1. 保存图片到[相机胶卷]
2.拥有一个[自定义相册]
3. 添加刚才保存的图片到[自定义相册]
二.Photos框架须知
PHAsset
一个PHAsset 对象代表一个显示在Photos应用中的 图片或者视频文件
PHAssetCollection
一个PHAssetCollection 代表一个图片或者视频的集合(其实就是相册)
PHAssetChangeRequest
凡是涉及到对PHAsset 的 增删改 都要使用
PHAssetChangeRequest
这个类
PHPhotoLibrary
这个对象不简单,一个 PHPhotoLibrary类的单例对象管理着Photos 应用内的访问和改变.
所有的PHAssetChangeRequest 的方法都需要在 [PHPhotoLibrary performChanges:completionHandler:] or -[PHPhotoLibrary performChangesAndWait:error:] 这个方法内调用,否则报错
- 查询一张照片,一个视频
[PHAsset fetchAsset....
- 查询一个相册
PHAssetCollection fetchAssetCollection...
- 对一张相片或者视频文件的 增 删 改
PHAssetChangeReques ...
对图片 视频的所有 create\ delete\modify 操作都用它
- 对一个相册的 ** 增 删 改 **
PHAssetCollectionChangeRequest...
对相册 的所有 create\ delete\modify 操作都用它
三.Photos 的具体相关操作
- 保存一张照片 到 相机胶卷
方式1: 同步方法
这个方法同步执行完成才会执行之后的代码,执行结果通过err 来返回
NSError *err = nil;
[[PHPhotoLibrary sharedPhotoLibrary] performChangesAndWait:^{
创建一张新照片并保存到Photos的[相机胶卷]
[PHAssetChangeRequest creationRequestForAssetFromImage:[UIImage imageNamed:@"abc"]];
} error:&err];
if(err){
@"执行失败"
}
else{
@" 执行成功"
}
方式2: 异步方法
这个方法异步执行,方法执行完毕 通过completionHandler 回调告诉执行结果
[[PHPhotoLibrary sharedPhotoLibrary]performChanges:^{
创建一张新照片并保存到Photos的[相机胶卷]
[PHAssetChangeRequest creationRequestForAssetFromImage:[UIImage imageNamed:@"abc"]];
} completionHandler:^(BOOL success, NSError * _Nullable error) {
// 执行完成通过这个回调 来告诉执行结果
if(err){
@" 执行失败"
}
else{
@" 执行成功"
}
}];
- 创建一个自定义相册 (有坑)
异步方法
[[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{
[PHAssetCollectionChangeRequest creationRequestForAssetCollectionWithTitle:@"mango的相册"];
} completionHandler:^(BOOL success, NSError * _Nullable error) {
if (error) {
@"创建自定义相册 失败";
}
else{
@"创建自定义相册 成功";
}
}];
同步方法
NSError *err = nil;
[[PHPhotoLibrary sharedPhotoLibrary] performChangesAndWait:^{
[PHAssetCollectionChangeRequest creationRequestForAssetCollectionWithTitle:@"mango的相册"];
} error:&err];
if (err) {
@"创建自定义相册 失败";
}
else{
@"创建自定义相册 成功";
}
上面的同步和异步方法虽然是创建自定义相册的但是如果不经思索直接调用方法创建,那么在photos 应用中就会出现多个同名的相册(方法被调用一次就会创建一个)
正确创建个人相册的方法是这样的:
/** 获取一个对应 名字的自定义相册,没有就创建一个新的 */
+(PHAssetCollection *)albumOfNamed:(NSString *)name{
if (name.length == 0) {
return nil;
}
//1.从所有的自定义相册 检查是否已经有 name 对应的自定义相册
PHFetchResult * assetCollectiopnResult = [PHAssetCollection fetchAssetCollectionsWithType:PHAssetCollectionTypeAlbum subtype:PHAssetCollectionSubtypeAlbumRegular options:nil];
for (PHAssetCollection *assetCollection in assetCollectiopnResult) {
if ([assetCollection.localizedTitle isEqualToString:name]) {
return assetCollection;
}
}
// 2. 没有找到,就自己创建一个
NSError *err = nil;
__block NSString *identifer = nil;
[[PHPhotoLibrary sharedPhotoLibrary] performChangesAndWait:^{
PHAssetCollectionChangeRequest *changeRequest = [PHAssetCollectionChangeRequest creationRequestForAssetCollectionWithTitle:name];
identifer = changeRequest.placeholderForCreatedAssetCollection.localIdentifier;
} error:&err];
if (err == nil) {
PHFetchResult * newAssetCollectiopnResult = [PHAssetCollection fetchAssetCollectionsWithLocalIdentifiers:@[identifer] options:nil];
return newAssetCollectiopnResult.firstObject;
}
return nil;
}
- 将一个照片asset 资源转换成UIImage 对象(有坑)
// 这个方法 可能会调用多次
[[PHImageManager defaultManager] requestImageForAsset:asset
targetSize:imgSize
contentMode:PHImageContentModeAspectFill
options:option
resultHandler:^(UIImage * _Nullable result, NSDictionary * _Nullable info) {
// 在这里处理接受获取到的image
}];
四.Photos 常用方法封装
- 保存照片到系统 的 相机胶卷相册
+(PHAsset *)saveImage2SystemCameraRollAlbum:(UIImage *)image{
if (image == nil) {
return nil;
}
NSError *err = nil;
__block NSString *assetIdentifier = nil;
[[PHPhotoLibrary sharedPhotoLibrary] performChangesAndWait:^{
PHAssetChangeRequest *request = [PHAssetChangeRequest creationRequestForAssetFromImage:image];
assetIdentifier = request.placeholderForCreatedAsset.localIdentifier;
} error:&err];
if (err == nil ) {
return [PHAsset fetchAssetsWithBurstIdentifier:assetIdentifier options:nil].firstObject;
}
return nil;
}
- 将 一堆 asset 保存到指定的相册 (将asset 从相机胶卷copy 一份到 assetCollection)
+(BOOL)saveAssetArr:(NSArray *)assetArr toAssetCollction:(PHAssetCollection *)assetCollection{
if(assetArr.count == 0 || assetCollection == nil){
return NO;
}
NSError *err = nil;
[[PHPhotoLibrary sharedPhotoLibrary] performChangesAndWait:^{
PHAssetCollectionChangeRequest *request = [PHAssetCollectionChangeRequest changeRequestForAssetCollection:assetCollection];
[request addAssets:assetArr];
//PHObjectPlaceholder *assetPlaceHolder =
//[request addAssets:@[assetPlaceHolder]]; 这里也可以放图片的站位对象,也是可以的
} error:&err];
return (err == nil);
}
- 获取系统的 相机胶卷相册
+(PHAssetCollection *)systemCameraRollAlbum{
PHFetchResult *assetCollectionResult = [PHAssetCollection fetchAssetCollectionsWithType:PHAssetCollectionTypeSmartAlbum subtype:PHAssetCollectionSubtypeSmartAlbumUserLibrary options:nil];
return assetCollectionResult.firstObject;
}
- 获取一个对应 名字的自定义相册,没有就创建一个新的
+(PHAssetCollection *)albumOfNamed:(NSString *)name{
if (name.length == 0) {
return nil;
}
//1.从所有的自定义相册 检查是否已经有 name 对应的自定义相册
PHFetchResult * assetCollectiopnResult = [PHAssetCollection fetchAssetCollectionsWithType:PHAssetCollectionTypeAlbum subtype:PHAssetCollectionSubtypeAlbumRegular options:nil];
for (PHAssetCollection *assetCollection in assetCollectiopnResult) {
if ([assetCollection.localizedTitle isEqualToString:name]) {
return assetCollection;
}
}
// 2. 没有找到,就自己创建一个
NSError *err = nil;
__block NSString *identifer = nil;
[[PHPhotoLibrary sharedPhotoLibrary] performChangesAndWait:^{
PHAssetCollectionChangeRequest *changeRequest = [PHAssetCollectionChangeRequest creationRequestForAssetCollectionWithTitle:name];
identifer = changeRequest.placeholderForCreatedAssetCollection.localIdentifier;
} error:&err];
if (err == nil) {
PHFetchResult * newAssetCollectiopnResult = [PHAssetCollection fetchAssetCollectionsWithLocalIdentifiers:@[identifer] options:nil];
return newAssetCollectiopnResult.firstObject;
}
return nil;
}
- 将 asset 作为相册的封面
-(BOOL)changeAssetAsAlbumCover:(PHAsset *)asset{
if(asset == nil){
return NO;
}
NSError *err = nil;
__weak typeof(self) weakSelf = self;
[[PHPhotoLibrary sharedPhotoLibrary] performChangesAndWait:^{
PHAssetCollectionChangeRequest *request = [PHAssetCollectionChangeRequest changeRequestForAssetCollection:weakSelf];
[request insertAssets:@[asset] atIndexes:[NSIndexSet indexSetWithIndex:0]];
} error:&err];
return err = nil;
}
- 获取指定相册的照片 资源
+(PHFetchResult *)allAssetInAssetCollcetion:(PHAssetCollection *)assetCollection{
if (assetCollection == nil) {
return nil;
}
return [PHAsset fetchAssetsInAssetCollection:assetCollection options:nil];
}
- 通过 一个 PHAsset 获取图片
+(void)requestImageForAsset:(PHAsset *)asset size:(CGSize)size callBack:(void(^)(UIImage *assetImage))callBack{
if (asset.mediaType == PHAssetMediaTypeImage) {
CGFloat scale = [UIScreen mainScreen].scale;
CGSize imgSize = CGSizeMake(size.width * scale, size.height * scale);
if (size.width == 0 || size.height == 0) {
imgSize = CGSizeMake(asset.pixelWidth, asset.pixelHeight);
}
// 这个option 保证在返回照片时只调用一次
PHImageRequestOptions *option = [self imageCallBackOnceOptions];
[[PHImageManager defaultManager] requestImageForAsset:asset
targetSize:imgSize
contentMode:PHImageContentModeAspectFill
options:option
resultHandler:^(UIImage * _Nullable result, NSDictionary * _Nullable info) {
if (callBack) {
callBack(result);
}
}];
}
else {
if (callBack) {
callBack(nil);
}
}
}
- 获取图片 回调 一次的 配置选择
+(PHImageRequestOptions *)imageCallBackOnceOptions{
PHImageRequestOptions *option = [[PHImageRequestOptions alloc]init];
// option.synchronous = YES;
option.resizeMode = PHImageRequestOptionsResizeModeExact;
option.deliveryMode = PHImageRequestOptionsDeliveryModeHighQualityFormat;
return option;
}
- 获取图片 同步 请求选择
+(PHImageRequestOptions *)imageSyncOptions{
PHImageRequestOptions *option = [self imageCallBackOnceOptions];
option.synchronous = YES;
return option;
}