最近在學 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
對保存視頻的封裝也是很是好的