最近在学 iOS相关技术(绘图篇实现画板功能)的时候设计到了两个经常使用的知识点,那就是保存图片到相册和葱相册中获取图片。php
只是我的比较好奇拓展一些技术,说的难听点叫作装牛角尖,好听点就是为了装逼而已,因此在保存相册的时候使用真及测试发现不能保存到我iPhone里 main的自定义相册里面,就查看文档和资料,也借鉴别人的分享实现了想要的功能,就把他给记录下来,这个虽然没有直接保存和获取经常使用可是也是一项很好的实用技术。html
一:首先来看看怎么获取相册的图片:git
1 // 弹出系统的相册
2 // 选择控制器(系统相册)
3 UIImagePickerController *picekerVc = [[UIImagePickerController alloc] init];
4
5 // 设置选择控制器的来源
6 // UIImagePickerControllerSourceTypePhotoLibrary 相册集
7 // UIImagePickerControllerSourceTypeSavedPhotosAlbum:照片库
8 picekerVc.sourceType = UIImagePickerControllerSourceTypeSavedPhotosAlbum;
9
10 // 设置代理 11 picekerVc.delegate = self; 12 13 // modal 14 [self presentViewController:picekerVc animated:YES completion:nil];
实现代理方法:github
1 #pragma mark - UIImagePickerControllerDelegate
2 // 当用户选择一张图片的时候调用
3 - (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
4 {
5 // 获取选中的照片
6 UIImage *image = info[UIImagePickerControllerOriginalImage];
7
8 // 把选中的照片画到画板上
9
10 _drawView.image = image;
11
12 // dismiss
13 [self dismissViewControllerAnimated:YES completion:nil];
14 }
注意:这里须要遵照两个协议:app
<UINavigationControllerDelegate,UIImagePickerControllerDelegate>iphone
关于只有UIImagePickerController却要遵照两个协议笔者也还在寻找答案,不过根据名字这个确定是跟导航控制器有关,可是这设计到了底层的东西,这里就很少作解释了。async
二:而后就是证实保存图片到系统的相册:测试
1 // 截屏 2 // 开启上下文 3 UIGraphicsBeginImageContextWithOptions(_drawView.bounds.size, NO, 0); 4 5 // 获取上下文 6 CGContextRef ctx = UIGraphicsGetCurrentContext(); 7 8 // 渲染图层 9 [_drawView.layer renderInContext:ctx]; 10 11 // 获取上下文中的图片 12 UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); 13 14 // 关闭上下文 15 UIGraphicsEndImageContext(); 16 17 18 // 保存画板的内容放入相册 19 // image:写入的图片 20 // completionTarget图片保存监听者 21 // 注意:之后写入相册方法中,想要监听图片有没有保存完成,保存完成的方法不能随意乱写 22 UIImageWriteToSavedPhotosAlbum(image, self, @selector(image:didFinishSavingWithError:contextInfo:), nil);
这里涉及到了图层的知识Quartz2d绘图,关于图层情查看笔者以前写的文章。ui
这里一样须要监听一下保存是否成功:url
1 // 监听保存完成,必须实现这个方法 2 - (void)image:(UIImage *)image didFinishSavingWithError:(NSError *)error contextInfo:(void *)contextInfo 3 { 4 NSLog(@"保存图片成功"); 5 }
三:最后就是保存图片到咱们在iphone中自定义相册:
保存照片还能够用ALAssetsLibrary
,ALAssetsLibrary
提供了咱们对iOS设备中的相片、视频的访问,是链接应用程序和相册之间访问的一个桥梁。
接下来,咱们来详细讲解一下关于系统相册权限获取、保存照片、建立本身的相簿等等功能。
这也是一种比较建立的做法,建立本身的相簿,而后把照片或者视频保存到本身的相簿中。相关代码以下:
1 ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init];
2 [library addAssetsGroupAlbumWithName:@"test" resultBlock:^(ALAssetsGroup *group) { 3 4 //建立相簿成功 5 6 } failureBlock:^(NSError *error) { 7 //失败 8 }];
这个方法也是将照片保存到系统相簿里面,不是保存到本身建立的相簿里面。代码以下:
1 ALAssetsLibrary *library = [[ALAssetsLibrary alloc]init]; 2 [library writeImageToSavedPhotosAlbum:image.CGImage orientation:(ALAssetOrientation)image.imageOrientation completionBlock:^(NSURL *asSetUrl,NSError *error){ 3 if (error) { 4 //失败 5 }else{ 6 UIAlertView *alert = [[UIAlertView alloc]initWithTitle:@"存储成功" 7 message:nil 8 delegate:nil 9 cancelButtonTitle:@"肯定" 10 otherButtonTitles:nil, nil]; 11 [alert show]; 12 13 } 14 }];
获取权限
在保存照片以前,若是用户关闭相册权限,这个时候是保存失败的。若是你不作任何处理,用户是不会知道本身保存失败了。因此,咱们能够在保存照片以前,作出相应的提示。如何获取这个权限呢?通常有两种方法:
建立相簿失败
保存照片失败
在上面两个方法建立本身的相簿和保存照片的失败结果里,咱们能够弹出获取照片权限失败的提示。咱们拿第一个建立相簿失败来举例:
1 ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init];
2 [library addAssetsGroupAlbumWithName:@"test" resultBlock:^(ALAssetsGroup *group) { 3 4 //建立相簿成功 5 6 } failureBlock:^(NSError *error) { 7 UIAlertView *alert = [[UIAlertView alloc]initWithTitle:@"存储失败" 8 message:@"请打开 设置-隐私-照片 来进行设置" 9 delegate:nil 10 cancelButtonTitle:@"肯定" 11 otherButtonTitles:nil, nil]; 12 [alert show]; 13 }];
在保存照片失败的结果里,咱们也能够弹出相应的提示,让用户打开应用程序的相册权限。
下面这段代码是在大谷歌里面找到的,亲自测试过是能够用的,整理以下:
1 #pragma mark - 建立相册
2 - (void)createAlbum
3 {
4 ALAssetsLibrary *assetsLibrary = [[ALAssetsLibrary alloc] init];
5 NSMutableArray *groups=[[NSMutableArray alloc]init]; 6 ALAssetsLibraryGroupsEnumerationResultsBlock listGroupBlock = ^(ALAssetsGroup *group, BOOL *stop) 7 { 8 if (group) 9 { 10 [groups addObject:group]; 11 } 12 13 else 14 { 15 BOOL haveHDRGroup = NO; 16 17 for (ALAssetsGroup *gp in groups) 18 { 19 NSString *name =[gp valueForProperty:ALAssetsGroupPropertyName]; 20 21 if ([name isEqualToString:@"iOSDevTip"]) 22 { 23 haveHDRGroup = YES; 24 } 25 } 26 27 if (!haveHDRGroup) 28 { 29 //do add a group named "XXXX" 30 [assetsLibrary addAssetsGroupAlbumWithName:@"iOSDevTip" 31 resultBlock:^(ALAssetsGroup *group) 32 { 33 [groups addObject:group]; 34 35 } 36 failureBlock:nil]; 37 haveHDRGroup = YES; 38 } 39 } 40 41 }; 42 //建立相簿 43 [assetsLibrary enumerateGroupsWithTypes:ALAssetsGroupAlbum usingBlock:listGroupBlock failureBlock:nil]; 44 45 [self saveToAlbumWithMetadata:nil imageData:UIImagePNGRepresentation(self.image) customAlbumName:@"iOSDevTip" completionBlock:^ 46 { 47 //这里能够建立添加成功的方法 48 49 } 50 failureBlock:^(NSError *error) 51 { 52 //处理添加失败的方法显示alert让它回到主线程执行,否则那个框框死活不愿弹出来 53 dispatch_async(dispatch_get_main_queue(), ^{ 54 55 //添加失败通常是由用户不容许应用访问相册形成的,这边能够取出这种状况加以判断一下 56 if([error.localizedDescription rangeOfString:@"User denied access"].location != NSNotFound ||[error.localizedDescription rangeOfString:@"用户拒绝访问"].location!=NSNotFound){ 57 UIAlertView *alert=[[UIAlertView alloc]initWithTitle:error.localizedDescription message:error.localizedFailureReason delegate:nil cancelButtonTitle:NSLocalizedString(@"ok", nil) otherButtonTitles: nil]; 58 59 [alert show]; 60 } 61 }); 62 }]; 63 } 64 65 - (void)saveToAlbumWithMetadata:(NSDictionary *)metadata 66 imageData:(NSData *)imageData 67 customAlbumName:(NSString *)customAlbumName 68 completionBlock:(void (^)(void))completionBlock 69 failureBlock:(void (^)(NSError *error))failureBlock 70 { 71 72 ALAssetsLibrary *assetsLibrary = [[ALAssetsLibrary alloc] init]; 73 __weak ALAssetsLibrary *weakSelf = assetsLibrary; 74 void (^AddAsset)(ALAssetsLibrary *, NSURL *) = ^(ALAssetsLibrary *assetsLibrary, NSURL *assetURL) { 75 [assetsLibrary assetForURL:assetURL resultBlock:^(ALAsset *asset) { 76 [assetsLibrary enumerateGroupsWithTypes:ALAssetsGroupAll usingBlock:^(ALAssetsGroup *group, BOOL *stop) { 77 78 if ([[group valueForProperty:ALAssetsGroupPropertyName] isEqualToString:customAlbumName]) { 79 [group addAsset:asset]; 80 if (completionBlock) { 81 completionBlock(); 82 } 83 } 84 } failureBlock:^(NSError *error) { 85 if (failureBlock) { 86 failureBlock(error); 87 } 88 }]; 89 } failureBlock:^(NSError *error) { 90 if (failureBlock) { 91 failureBlock(error); 92 } 93 }]; 94 }; 95 [assetsLibrary writeImageDataToSavedPhotosAlbum:imageData metadata:metadata completionBlock:^(NSURL *assetURL, NSError *error) { 96 if (customAlbumName) { 97 [assetsLibrary addAssetsGroupAlbumWithName:customAlbumName resultBlock:^(ALAssetsGroup *group) { 98 if (group) { 99 [weakSelf assetForURL:assetURL resultBlock:^(ALAsset *asset) { 100 [group addAsset:asset]; 101 if (completionBlock) { 102 completionBlock(); 103 } 104 } failureBlock:^(NSError *error) { 105 if (failureBlock) { 106 failureBlock(error); 107 } 108 }]; 109 } else { 110 AddAsset(weakSelf, assetURL); 111 } 112 } failureBlock:^(NSError *error) { 113 AddAsset(weakSelf, assetURL); 114 }]; 115 } else { 116 if (completionBlock) { 117 completionBlock(); 118 } 119 } 120 }]; 121 }
ALAssetsLibrary+CustomPhotoAlbum保存照片
github
上有一个项目ALAssetsLibrary+CustomPhotoAlbum :( https://github.com/Kjuly/ALAssetsLibrary-CustomPhotoAlbum ),讲保存照片作了很好的封装。使用以前记得先导入头文件:
#import "ALAssetsLibrary+CustomPhotoAlbum.h"
保存照片到本身的相簿,直接调用:
1 ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init]; 2 [library saveImage:self.image toAlbum:@"gang" completion:^(NSURL *assetURL, NSError *error) { 3 if (!error) { 4 5 } 6 } failure:^(NSError *error) { 7 8 }];
ALAssetsLibrary+CustomPhotoAlbum
对保存视频的封装也是很是好的