保存(獲取)圖片到(自定義)相冊


最近在學 iOS相關技術(繪圖篇實現畫板功能)的時候設計到了兩個常用的知識點,那就是保存圖片到相冊和蔥相冊中獲取圖片。

只是個人比較好奇拓展一些技術,說的難聽點叫做裝牛角尖,好聽點就是爲了裝逼而已,所以在保存相冊的時候使用真及測試發現不能保存到我iPhone裏 main的自定義相冊裏面,就查看文檔和資料,也借鑑別人的分享實現了想要的功能,就把他給記錄下來,這個雖然沒有直接保存和獲取常用但是也是一項很好的實用技術

一:首先來看看怎麼獲取相冊的圖片:

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];

實現代理方法:

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 }

注意:這裏需要遵守兩個協議:

<UINavigationControllerDelegate,UIImagePickerControllerDelegate>

關於只有UIImagePickerController卻要遵守兩個協議筆者也還在尋找答案,不過根據名字這個肯定是跟導航控制器有關,但是這設計到了底層的東西,這裏就不多做解釋了。

二:然後就是證明保存圖片到系統的相冊:

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繪圖,關於圖層情查看筆者之前寫的文章。

這裏同樣需要監聽一下保存是否成功:

1 // 監聽保存完成,必須實現這個方法
2 - (void)image:(UIImage *)image didFinishSavingWithError:(NSError *)error contextInfo:(void *)contextInfo
3 {
4      NSLog(@"保存圖片成功");
5 }

三:最後就是保存圖片到我們在iphone中自定義相冊:

保存照片還可以用ALAssetsLibraryALAssetsLibrary提供了我們對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. 創建相簿失敗

  2. 保存照片失敗

在上面兩個方法創建自己的相簿保存照片的失敗結果裏,我們可以彈出獲取照片權限失敗的提示。我們拿第一個創建相簿失敗來舉例:

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對保存視頻的封裝也是非常好的。我現在項目中用的也是這個第三方來保存照片和視頻。因爲不錯,所以推薦給大家使用。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章