一、保存圖片到自定義相冊的三個步驟
-
1.保存圖片到相冊【相機膠卷】
1>、C語言保存
2>、#import <AssetsLibrary/AssetsLibrary.h> 保存AssetsLibrary框架: iOS9 之后開始被廢棄
3>、#import <Photos/Photos.h> 保存
Photos框架 iOS 8 開始就可以用了
2.擁有一個自定義相冊:使用
AssetsLibrary
與Photos
框架3.將剛才保存到【相機膠卷中的圖片】引用到【自定義的相冊】:使用
AssetsLibrary
與Photos
框架
二、單純的C語言保存圖片到相冊(不使用AssetsLibrary
與Photos
框架)
-
2.1、保存圖片到相冊
/** <#Description#> 第1個參數:UIIMage 對象 第2個參數:監聽對象 第3個參數:保存后所走【監聽對象】的方法 第4個參數:描述文字,一般為 niul */ UIImageWriteToSavedPhotosAlbum(self.photoimageView.image, self, @selector(image:didFinishSavingWithError:contextInfo:), nil); #pragma mark 保存成功后所走的方法 - (void)image:(UIImage *)image didFinishSavingWithError:(NSError *)error contextInfo:(void *)contextInfo{ // 保存完畢 if (error) { NSLog(@"保存失敗"); }else{ NSLog(@"保存成功"); } }
提示:上面第三個參數是要按照蘋果的格式來寫方法名的,點擊方法進去 我們可以到如下代碼:
// Adds a photo to the saved photos album. The optional completionSelector should have the form:
// - (void)image:(UIImage *)image didFinishSavingWithError:(NSError *)error contextInfo:(void *)contextInfo;
蘋果讓我們按照他們的格式來寫方法,我們可以把他們的方法名替換為任意的名字,如:- (void)a:(UIImage *)image b:(NSError *)error c:(void *)contextInfo;
三、Photos 框架
-
3.1、Photos 框架基本認識,我們可以在
Help
->Developer Documentation
-> 選擇OC或者Swift 搜索Photos
Photos 框架檢索
Photos 是用來處理 視頻 與 圖片 的,下面是其主要的類-
<1>、
PHAsset
:一個 PHAsset 對象就代表相冊中的一張圖片或者一個視頻(1)、查:[PHAsset fetch.....]
(2)、增刪改:PHAssetChangeRequest,改變圖片 (包括 圖片/視頻 相關的所有改動操作) <2>、:
PHAssetCollection
: 一個PHAssetCollection就代表一個相冊
(1)、查:[PHAssetCollection fetch.....]
(2)、增刪改:PHAssetCollectionChangeRequest,改變相冊 (包括 相冊 相關的所有改動操作)
提示:所有的增刪改的操作都要放到:
-[PHPhotoLibrary performChanges:completionHandler:] or -[PHPhotoLibrary performChangesAndWait:error:]'
方法里面 -
-
3.2、使用 Photos 框架保存圖片到【相機膠卷】
-
異步操作保存到相冊
[[PHPhotoLibrary sharedPhotoLibrary]performChanges:^{ [PHAssetChangeRequest creationRequestForAssetFromImage:self.photoimageView.image]; } completionHandler:^(BOOL success, NSError * _Nullable error) { if (error) { [SVProgressHUD showErrorWithStatus:@"保存失敗"]; }else{ [SVProgressHUD showErrorWithStatus:@"保存成功"]; } }];
-
同步操作保存到相冊
NSError *error = nil; [[PHPhotoLibrary sharedPhotoLibrary] performChangesAndWait:^{ [PHAssetChangeRequest creationRequestForAssetFromImage:self.photoimageView.image]; } error:&error]; if (error) { [SVProgressHUD showErrorWithStatus:@"保存失敗"]; }else{ [SVProgressHUD showErrorWithStatus:@"保存成功"]; }
提示:使用 Photos 框架保存圖片到【相機膠卷】必須把代碼放到上面的兩個方法里面,否則會報下面的錯
reason: 'This method can only be called from inside of -[PHPhotoLibrary performChanges:completionHandler:] or -[PHPhotoLibrary performChangesAndWait:error:]'
-
-
3.3、創建新的相冊(自定義一個屬于自己app的相冊),提示:創建相冊之前要先判斷相冊是否存在,存在就不再創建
NSError *error = nil; [[PHPhotoLibrary sharedPhotoLibrary] performChangesAndWait:^{ // 獲取app的名字 NSString *appName = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleName"]; // 創建一個自定義的相冊 [PHAssetCollectionChangeRequest creationRequestForAssetCollectionWithTitle: appName]; } error:&error]; if (error) { [SVProgressHUD showErrorWithStatus:@"創建相冊失敗"]; }else{ [SVProgressHUD showErrorWithStatus:@"創建相冊成功"]; }
提示一:
kCFBundleNameKey = @"CFBundleName"
,下面的兩句是一個意思- NSString *appName = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleName"];
下面是:C 的strting轉為NSString - NSString *appName = [[[NSBundle mainBundle] infoDictionary] objectForKey:(NSString *)kCFBundleNameKey];
提示二:Foundation 和 Core Foundation 的數據類型可以相互轉換,比如:NSString * 和 CFStringRef,如下面的例子:
NSString *string = (NSString *)kCFBundleNameKey; CFStringRef string = (CFStringRef)@"name";
- NSString *appName = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleName"];
-
3.4、查詢相冊 (自定義相冊或者系統相冊)
/** PHAssetCollectionTypeAlbum = 1, 自定義相冊(普通的相冊) PHAssetCollectionTypeSmartAlbum = 2, 智能相冊(系統自帶的相冊),如:Camera Roll PHAssetCollectionTypeMoment = 3, 按照時刻分的相冊 */ // 相機膠卷相冊,打印:Camera Roll // PHFetchResult<PHAssetCollection *> *collections = [PHAssetCollection fetchAssetCollectionsWithType:PHAssetCollectionTypeSmartAlbum subtype:PHAssetCollectionSubtypeSmartAlbumUserLibrary options:nil]; // 自定義相冊,打印:自定義相冊的名字 PHFetchResult<PHAssetCollection *> *collections = [PHAssetCollection fetchAssetCollectionsWithType:PHAssetCollectionTypeAlbum subtype:PHAssetCollectionSubtypeAlbumRegular options:nil]; for (PHAssetCollection *collection in collections) { NSLog(@"相冊的名字=%@",collection.localizedTitle); }
-
3.5.創建相冊與查詢相冊合在一起,如下
// 獲取app的名字 NSString *appName = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleName"]; /** PHAssetCollectionTypeAlbum = 1, 自定義相冊(普通的相冊) PHAssetCollectionTypeSmartAlbum = 2, 智能相冊(系統自帶的相冊),如:Camera Roll PHAssetCollectionTypeMoment = 3, 按照時刻分的相冊 */ // 相機膠卷相冊,打印:Camera Roll // PHFetchResult<PHAssetCollection *> *collections = [PHAssetCollection fetchAssetCollectionsWithType:PHAssetCollectionTypeSmartAlbum subtype:PHAssetCollectionSubtypeSmartAlbumUserLibrary options:nil]; // 自定義相冊,打印:自定義相冊的名字 PHFetchResult<PHAssetCollection *> *collections = [PHAssetCollection fetchAssetCollectionsWithType:PHAssetCollectionTypeAlbum subtype:PHAssetCollectionSubtypeAlbumRegular options:nil]; // 自己的相冊 PHAssetCollection *appCollection = nil; for (PHAssetCollection *collection in collections) { NSLog(@"相冊的名字=%@",collection.localizedTitle); if ([collection.localizedTitle isEqualToString:appName]) { appCollection = collection; break; } } if (appCollection == nil) { NSError *error = nil; __block NSString *createCollectionID = nil; [[PHPhotoLibrary sharedPhotoLibrary] performChangesAndWait:^{ // 獲取app的名字 NSString *appName = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleName"]; // 獲取相冊的唯一標識符 createCollectionID = [PHAssetCollectionChangeRequest creationRequestForAssetCollectionWithTitle:appName].placeholderForCreatedAssetCollection.localIdentifier; } error:&error]; if (error) { [SVProgressHUD showErrorWithStatus:@"創建相冊失敗"]; }else{ appCollection = [PHAssetCollection fetchAssetCollectionsWithLocalIdentifiers:@[createCollectionID] options:nil].firstObject; [SVProgressHUD showErrorWithStatus:@"創建相冊成功"]; } } // 相冊一定存在 NSLog(@"相冊已經存在");
提示:這里有一個技術點就是:根據創建相冊返回的相冊唯一標識符獲取相冊對象,如下代碼:
// 自己的相冊 PHAssetCollection *appCollection = nil; if (appCollection == nil) { NSError *error = nil; __block NSString *createCollectionID = nil; [[PHPhotoLibrary sharedPhotoLibrary] performChangesAndWait:^{ // 獲取app的名字 NSString *appName = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleName"]; // 獲取相冊的唯一標識符 createCollectionID = [PHAssetCollectionChangeRequest creationRequestForAssetCollectionWithTitle:appName].placeholderForCreatedAssetCollection.localIdentifier; } error:&error]; if (error) { [SVProgressHUD showErrorWithStatus:@"創建相冊失敗"]; }else{ appCollection = [PHAssetCollection fetchAssetCollectionsWithLocalIdentifiers:@[createCollectionID] options:nil].firstObject; [SVProgressHUD showErrorWithStatus:@"創建相冊成功"]; } }
- 再次提示:只有上面的block代碼執行完才代表相冊可能存在,所以,獲取PHAssetCollection放在了下面
-
3.6、保存圖片到自定義的相冊
-(void)savePhotosToAppPhotoCollection{ // 同步操作保存到【相機膠卷】 __block PHObjectPlaceholder *placeholderForCreatedAsset; NSError *error = nil; [[PHPhotoLibrary sharedPhotoLibrary] performChangesAndWait:^{ placeholderForCreatedAsset = [PHAssetChangeRequest creationRequestForAssetFromImage:self.photoimageView.image].placeholderForCreatedAsset; } error:&error]; if (error) { [SVProgressHUD showErrorWithStatus:@"保存圖片失敗"]; return; } // 獲得自定義相冊 PHAssetCollection *createCollection = [JKPhotosKit createPHAssetCollection]; if (createCollection == nil) { [SVProgressHUD showErrorWithStatus:@"創建相冊失敗"]; return; } // 添加剛才保存的圖片到 【自定義相冊】 [[PHPhotoLibrary sharedPhotoLibrary] performChangesAndWait:^{ // 獲取自定義對象的操作對象 PHAssetCollectionChangeRequest *request = [PHAssetCollectionChangeRequest changeRequestForAssetCollection:createCollection]; // 把圖片插入到自定義相冊的第一個位置 [request insertAssets:@[placeholderForCreatedAsset] atIndexes:[NSIndexSet indexSetWithIndex:0]]; } error:&error]; if (error) { [SVProgressHUD showErrorWithStatus:@"保存圖片失敗"]; }else{ [SVProgressHUD showSuccessWithStatus:@"保存圖片成功"]; } }
-
3.7、用戶相冊權限的判斷
// 請求或者訪問用戶訪問權限: // 如果還沒有做出選擇,會自動彈框,用戶對彈框做出選擇后才會調用block; // 如果用戶之前已經做出過選擇,會自動執行block /** PHAuthorizationStatusNotDetermined = 0,還沒決定 PHAuthorizationStatusRestricted = 1,沒有授權,不能訪問用戶相冊 PHAuthorizationStatusDenied = 2,用戶拒絕這個應用 PHAuthorizationStatusAuthorized = 3 用戶授權這個app訪問這個相冊 */ // 獲取用戶之前的狀態 PHAuthorizationStatus oldStatus = [PHPhotoLibrary authorizationStatus]; [PHPhotoLibrary requestAuthorization:^(PHAuthorizationStatus status) { // 用戶決絕當前 App 訪問相冊 dispatch_async(dispatch_get_main_queue(), ^{ if (status == PHAuthorizationStatusDenied) { if (oldStatus != PHAuthorizationStatusDenied) { // 提醒用戶打開開關 }else{ } }else if (status == PHAuthorizationStatusAuthorized){ // 用戶允許當前 App 訪問相冊 [self trueSaveImageToAppPhotoCollection:saveImage]; }else if (status == PHAuthorizationStatusRestricted){ // 因系統原因無法訪問相冊 [SVProgressHUD showErrorWithStatus:@"因系統原因無法訪問相冊"]; } }); }];
提示:上面所有的完整代碼都在
JKPhotosKit
類里面,需要的請下載 demo- JKPhotosKit 類的使用方法:保存圖片到自定的相冊
[JKPhotosKit savePhotosToAppPhotoCollection:UIImage對象
];
效果圖
- JKPhotosKit 類的使用方法:保存圖片到自定的相冊
完整代碼都在 JKPhotosKit
類里面,需要的請下載 demo