一. 最簡單的保存函數
- UIImage的函數來保存圖片
較為簡單, 只需要一個函數一個方法就可以保存
-
但是不能創建相冊, 保存的圖片會直接保存到默認的系統相冊中
/** 該函數用于將圖片保存到系統相冊中 UIImage * _Nonnull image : 要保存的圖片 id _Nullable completionTarget : 調用completionSelector方法的對象, 一般為self SEL _Nullable completionSelector : 當保存完成調用的方法, 是一個系統指定的方法 void * _Nullable contextInfo : 上下文信息, 用于傳給完成后的回調方法, 一般為nil */ UIImageWriteToSavedPhotosAlbum(_image, self, @selector(image:didFinishSavingWithError:contextInfo:), nil); - (void)image:(UIImage *)image didFinishSavingWithError:(NSError *)error contextInfo:(void *)contextInfo { if (error) { NSLog(@"保存失敗"); } else { NSLog(@"保存成功"); } }
-
注意點
- 第三個參數一定要使用系統的回調方法, 否則這個方法會報錯
- 系統指定的
image: didFinishSavingWithError: contextInfo:
方法一定要實現, 否則也會出現問題
二. 使用PHPhotoLibrary來保存圖片
-
框架的簡單介紹:
- PHPhotoLibrary類, 專門用于管理系統的相片, 相簿等功能, 他可以獲取系統相冊中的相片信息, 也可以將App中獲取的圖片/相片存到手機相冊中, 以及iCloud Photos中.
- 對于手機相冊的各種操作, 幾乎都是通過PHPhotoLibrary的單例對象, 在ChangeBlock中, 以
ChangeRequest
來執行的- 相片請求操作: PHAssetChangeRequest
- 相冊請求操作: PHAssetCollectionChangeRequest
- 相冊列表請求操作: PHCollectionListChangeRequest(小的暫時沒試過)
- PHObjectPlaceholder對象
- 這個對象是用于存儲圖片時的占位對象
- 如果你想保存一個圖片到一個相冊中, 需要先將這個占位對象添加到相冊中, 當ChangeBlock調用結束之后, 會根據占位對象的標識符搜索到占位對象的所在位置, 然后在保存圖片
- PHAuthorization: 用于查看當前App的相冊授權狀態
- 這個類用于獲取當前你的App, 系統對其相冊訪問權限的授權狀態
- 通過對四種不同的授權狀態的判斷, 我們可以做出對應的操作
- PHAuthorizationStatusNotDetermined : 用戶還沒有決定是否授權
- PHAuthorizationStatusRestricted : 訪問權限受限制, 這個很少見, 如家長模式的限制才會有
- PHAuthorizationStatusDenied : 用戶拒絕App訪問相冊
- PHAuthorizationStatusAuthorized : 用戶已經授權了訪問
- PHFetchResult: 檢索相簿中的相冊/相片
- 這個類創建的對象, 是一個有序集合, 可以用于保存系統相簿中的相片/相冊的搜索結果列表
- 該對象的每個元素, 都有一個localizedTitle, 即搜索得到的相片/相冊的名稱, 可以通過這個屬性來獲得指定的相冊/相片
- 一般是通過遍歷的方式, 然后判斷localizedTitle, 取得我們想要的相片/相冊
-
保存圖片的步驟
- 提供給外界調用的方法, 通過傳入要保存的圖片, 和指定的相冊名稱來保存一張圖片
在這個方法中, 要獲取當前App的相冊授權狀態
如果用戶授權了, 就直接調用步驟2的方法, 保存圖片
如果用戶沒有確定是否授權, 要創建授權申請, 讓用戶選擇
-
如果用戶已經拒絕了授權, 要顯示一個指示框, 讓用戶去打開授權
+ (void)saveImage:(UIImage *)image assetCollectionName:(NSString *)collectionName { // 1. 獲取當前App的相冊授權狀態 PHAuthorizationStatus authorizationStatus = [PHPhotoLibrary authorizationStatus]; // 2. 判斷授權狀態 if (authorizationStatus == PHAuthorizationStatusAuthorized) { // 2.1 如果已經授權, 保存圖片(調用步驟2的方法) [self saveImage:image toCollectionWithName:collectionName]; } else if (authorizationStatus == PHAuthorizationStatusNotDetermined) { // 如果沒決定, 彈出指示框, 讓用戶選擇 [PHPhotoLibrary requestAuthorization:^(PHAuthorizationStatus status) { // 如果用戶選擇授權, 則保存圖片 if (status == PHAuthorizationStatusAuthorized) { [self saveImage:image toCollectionWithName:collectionName]; } }]; } else { [SVProgressHUD showWithStatus:@"請在設置界面, 授權訪問相冊"]; } }
- 用于保存圖片的方法, 通過外接接口獲取到的圖片, 相冊名稱來進行保存
將一個相片保存到一個自定義的相冊, 需要同時創建相片變動請求和相冊變動請求
根據傳入的相冊名, 要判斷一下當前系統是否有這個相冊(這里需要步驟3的方法, 傳入相冊名稱, 來獲取相冊)
-
在這個步驟, 需要用到的四個核心對象為PHPhotoLibrary, PHAssetCollectionChangeRequest, PHAssetChangeRequest, 以及PHObjectPlaceholder
// 保存圖片 + (void)saveImage:(UIImage *)image toCollectionWithName:(NSString *)collectionName { // 1. 獲取相片庫對象 PHPhotoLibrary *library = [PHPhotoLibrary sharedPhotoLibrary]; // 2. 調用changeBlock [library performChanges:^{ // 2.1 創建一個相冊變動請求 PHAssetCollectionChangeRequest *collectionRequest; // 2.2 取出指定名稱的相冊 PHAssetCollection *assetCollection = [self getCurrentPhotoCollectionWithTitle:collectionName]; // 2.3 判斷相冊是否存在 if (assetCollection) { // 如果存在就使用當前的相冊創建相冊請求 collectionRequest = [PHAssetCollectionChangeRequest changeRequestForAssetCollection:assetCollection]; } else { // 如果不存在, 就創建一個新的相冊請求 collectionRequest = [PHAssetCollectionChangeRequest creationRequestForAssetCollectionWithTitle:collectionName]; } // 2.4 根據傳入的相片, 創建相片變動請求 PHAssetChangeRequest *assetRequest = [PHAssetChangeRequest creationRequestForAssetFromImage:image]; // 2.4 創建一個占位對象 PHObjectPlaceholder *placeholder = [assetRequest placeholderForCreatedAsset]; // 2.5 將占位對象添加到相冊請求中 [collectionRequest addAssets:@[placeholder]]; } completionHandler:^(BOOL success, NSError * _Nullable error) { // 3. 判斷是否出錯, 如果報錯, 聲明保存不成功 if (error) { [SVProgressHUD showErrorWithStatus:@"保存失敗"]; } else { [SVProgressHUD showSuccessWithStatus:@"保存成功"]; } }]; }
- 步驟三用于獲取當前系統中是否有指定的相冊
如果有的話, 就返回已有相冊
如果沒有的話, 就返回nil, 讓步驟二去創建一個新的系統相冊
此處需要用到的關鍵類為: FHFetchResult, 用于搜索相冊/相片名稱的集合對象
-
通過搜索結果的localizedTitle來找到對應的相冊
+ (PHAssetCollection *)getCurrentPhotoCollectionWithTitle:(NSString *)collectionName { // 1. 創建搜索集合 PHFetchResult *result = [PHAssetCollection fetchAssetCollectionsWithType:PHAssetCollectionTypeAlbum subtype:PHAssetCollectionSubtypeAlbumRegular options:nil]; // 2. 遍歷搜索集合并取出對應的相冊 for (PHAssetCollection *assetCollection in result) { if ([assetCollection.localizedTitle containsString:collectionName]) { return assetCollection; } } return nil; }
- 提供給外界調用的方法, 通過傳入要保存的圖片, 和指定的相冊名稱來保存一張圖片