先明白一个常识性的东西,我们平时保存图片,都是保存在相机胶卷的,如果做自己app的相册,是添加了索引,指向的还是胶卷中的相片,所以删除胶卷的相片,会影响到app相册内的图片,删除app相册内的图片,不会影响胶卷的图片
仅保存图片到相册的
- 方法1
- (void)saveImage:(UIImage *)image
{
// Adds a photo to the saved photos album. The optional completionSelector should have the form:
//UIKIT_EXTERN void UIImageWriteToSavedPhotosAlbum(UIImage *image, __nullable id completionTarget, __nullable SEL completionSelector, void * __nullable contextInfo) API_UNAVAILABLE(tvOS);
UIImageWriteToSavedPhotosAlbum(image, self, @selector(image:didFinishSavingWithError:contextInfo:), nil);
//注意参数 : completionSelector : The optional completionSelector should have the form:
// - (void)image:(UIImage *)image didFinishSavingWithError:(NSError *)error contextInfo:(void *)contextInfo;
//方法名称可以自定义,但是必须要有3个参数,不然会崩溃:数组越界,
}
- (void)image:(UIImage *)image didFinishSavingWithError:(NSError *)error contextInfo:(void *)contextInfo
{
if(error){
NSLog(@"保存失败");
}else{
NSLog(@"保存成功");
}
}
- 方法2
- (void)saveImage1:(UIImage *)image title:(NSString *)title
{
NSError *error = nil;
[[PHPhotoLibrary sharedPhotoLibrary] performChangesAndWait:^{
[PHAssetChangeRequest creationRequestForAssetFromImage:image];
} error:&error];
if(error){
NSLog(@"保存到图片胶卷失败");
return;
}else{
NSLog(@"保存到图片胶卷成功");
}
}
将图片保存到自定义相册/自己app的相册
这里我们使用 #import
框架
1.先说明一下实现
1.将图片保存到相机胶卷
2.创建我们的自定义相册
3.添加我们保存在相机胶卷的图片到自定义相册
2.然后粗略介绍一下必回点
常用的2个类
- PHAsset : 一个 PHAsset 对象,就代表相册中的一个图片或者视频
- PHAssetCollection : 一个 PHAssetCollection 就代表一个相册
对两个类的操作
- 查 : [PHAsset fetchAssets...] / [PHAssetCollection fetchAssets...]
- 增删改 : PHAssetChangeRequest / PHAssetCollectionChangeRequest
注意点:增删改必须在下面block中
//PHAssetChangeRequest can only be created or used within a -[PHPhotoLibrary performChanges:] or -[PHPhotoLibrary performChangesAndWait:] block.
// PHAssetCollectionChangeRequest can only be created or used within a -[PHPhotoLibrary performChanges:] or -[PHPhotoLibrary performChangesAndWait:] block.
3.开始实现
- 创建一个相册,肯定要先查看有没有创建过啦,我们来
遍历相册
,
//如果不遍历,点击保存按钮,会创建一个相册,那么多次保存就会创建多个
/* 参数1 :PHAssetCollectionType
PHAssetCollectionTypeAlbum = 1,普通相册,自定义的相册
PHAssetCollectionTypeSmartAlbum = 2, 智能相册,系统自带的相册
PHAssetCollectionTypeMoment = 3,时间相册,按日期划分的那种
参数2:subtype
PHAssetCollectionSubtypeAlbumRegular : 这里使用标准的自定义的相册
PHAssetCollectionSubtypeSmartAlbumUserLibrary : 智能相册时使用
*/
/*
返回值:(PHFetchResult *)
拥有快速遍历,可以使用快速遍历,遍历出所有相册
*/
- (PHAssetCollection *)searchAlbum:(NSString *)title
{
PHFetchResult *collection = [PHAssetCollection fetchAssetCollectionsWithType:PHAssetCollectionTypeAlbum subtype:PHAssetCollectionSubtypeAlbumRegular options:nil];
PHAssetCollection * ac = nil;
for (PHAssetCollection * c in collection) {
//相册名
NSLog(@"%@",c.localizedTitle);
//如果找到了相册
if([c.localizedTitle isEqualToString:title]){
return c;;
}
}
if (ac == nil) {
//如果相册不存在,创建相册,并拿到相册
ac = [self createAsetsColltion:title];
}
return ac;
}
- 未查到我们要的自定义相册,我们来
创建一个相册
- (PHAssetCollection *)createAsetsColltion:(NSString *)title
{
NSError *error = nil;
PHAssetCollection *co = nil;//空相册
__block NSString *indx;//标识
[[PHPhotoLibrary sharedPhotoLibrary] performChangesAndWait:^{
//常规创建相册
// [PHAssetCollectionChangeRequest creationRequestForAssetCollectionWithTitle:title];
//现在问题出来了,我们创建一个相册,首先应该查询相册是否创建过,在查询到未创建相册的时候,我们来创建一个相册,
//当我们有自定义相册的时候,遍历获取相册,赋值给相册对象
//当没有我们自定义相册的时候,遍历获取相册为nil,之后创建相册,但是我们的本意是通过遍历来拿到相册对象的,总不能创建相册后再次遍历一遍吧,那么怎么拿到创建的这个相册对象呢
//1.创建一个相册,并获取占位相册(将要创建的相册)的唯一标识,这时候相册还没创建成功,要出了block后
indx = [PHAssetCollectionChangeRequest creationRequestForAssetCollectionWithTitle:title].placeholderForCreatedAssetCollection.localIdentifier;
} error:&error];
//2.根据相册标识数组获取相册,因为这里只有一个
co = [PHAssetCollection fetchAssetCollectionsWithLocalIdentifiers:@[indx] options:nil].firstObject;
if(error){
NSLog(@"创建失败");
return nil;
}else{
NSLog(@"创建成功");
return co;
}
}
- 前面已经保存图片到相机胶卷,并且获取到了相册,那接下来怎么把相机胶卷的图片保存到自定义相册呢,又应该在什么时候来做把相机胶卷的图片保存到自定义相册的这个操作呢
答案是,在保存图片到相机胶卷的时候,直接把图片也保存到自定义相册
我们来修改之前的保存方法
- (void)saveImage1:(UIImage *)image title:(NSString *)title
{
NSError *error = nil;
__block PHObjectPlaceholder *placeholder = nil;//占位图片对象
[[PHPhotoLibrary sharedPhotoLibrary] performChangesAndWait:^{
// [PHAssetChangeRequest creationRequestForAssetFromImage:image];
//现在问题来了,这里只是保存到相机胶卷,如果要把图片保存到自己的app的相册,就得先拿到这个图片,怎么办呢
//拿到占位对象,也可以和创建相册一样是拿到标识indx,不过这里没必要
placeholder = [PHAssetChangeRequest creationRequestForAssetFromImage:image].placeholderForCreatedAsset;
} error:&error];
if(error){
NSLog(@"保存到图片胶卷失败");
return;
}else{
NSLog(@"保存到图片胶卷成功");
//遍历拿到相册
PHAssetCollection *ac = [self searchAlbum:title];
//往相册添加图片
[[PHPhotoLibrary sharedPhotoLibrary] performChangesAndWait:^{
PHAssetCollectionChangeRequest *request = [PHAssetCollectionChangeRequest changeRequestForAssetCollection:ac];
//添加到app相册
//[request addAssets:@[placeholder]];//(nonnull id) 支持快速遍历即可,数组/字典等
//以上操作看似已经完成,其实还差一步,我们都知道,当我们保存一张图片,相册的封面就是我们最新保存的图片,如果这样添加,只是往后面添加图片,封面会一直是保存的第一个图片,所以,插入到0
[request insertAssets:@[placeholder] atIndexes:[NSIndexSet indexSetWithIndex:0]];
} error:&error];
}
}
- 结束了吗?
//不不,当app第一次安装时,保存图片是要获取权限的,当弹出选择框还没做出选择的时候,代码依旧在往下执行,图片就会保存失败,所以要判断权限后,在去做保存
//检查访问权限,当用户选择后执行block,你以为这样就行了吗,刚点了拒绝,然后就检测权限提醒你拒绝了- emm,那么
//先拿出之前权限的状态
PHAuthorizationStatus oldStatus = [PHPhotoLibrary authorizationStatus];
//然后检查权限
[PHPhotoLibrary requestAuthorization:^(PHAuthorizationStatus status) {
/*
PHAuthorizationStatusNotDetermined = 0, 用户还未选择
PHAuthorizationStatusRestricted,未授权,且用户不可以去设置中设置允许和不允许授权
PHAuthorizationStatusDenied, 用户拒绝访问
PHAuthorizationStatusAuthorized 用户已授权
*/
if (status == PHAuthorizationStatusAuthorized) {
//保存图片到相机胶卷,并存储到app相册
[self saveImage1:image title:title];
}else if (status == PHAuthorizationStatusDenied && oldStatus == PHAuthorizationStatusNotDetermined){
//本次点了拒绝,并且之前还没做过选择,进行提醒
NSLog(@"拒绝访问相册了,去设置吧");
}else{NSLog(@"因系统原因无法访问相册");}
}];
好了,现在是真的只有最后一步了,设置info.plist
Privacy - Photo Library Additions Usage Description : "提示语“