Come On
這篇文章主要是介紹在IOS8之后官方給出的系統框架Photos。
首先先看一看這個框架的分類:
PHAsset: 代表照片庫中的一個資源實體,可以理解為一張照片,在打印的時候,可以清楚的看 見里面包含了照片的時間、標題等信息。
PHFetchOptions: 獲取資源時的參數,可以傳 nil,即使用系統默認值
PHFetchResult: 表示結果集,可以使相冊集合,可以使照片實體集合。
PHAssetCollection: 表示一個相冊或者一個時刻,或者是一個「智能相冊(系統提供的特定的一
系列相冊,例如:最近刪除,視頻列表,收藏等等,如下圖所示)
PHCollectionList :經過一番嘗試,這個的使用和上面PHAssetCollection差不多,不做詳細解釋啦。
PHImageManager: 用于處理資源的加載,加載圖片的過程帶有緩存處理,可以通過傳入一個 PHImageRequestOptions 控制資源的輸出尺寸等規(guī)格
PHImageRequestOptions: 如上面所說,控制加載圖片時的一系列參數
由于個人開發(fā)中主要用到如何將圖片儲存到本地相冊中,所以就只是對涉及的用法作一個簡單的說明。
大體的思路:
- 獲取當前用戶的相冊授權(可以訪問相冊還是拒絕)。
以下都是在允許的訪問的權限下進行的: - 通過PHFetchResult,并且利用圖片獲得PHAsset對象,從而標記需要儲存的圖片。
- 通過PHFetchResult去初始化一個利用相冊名稱的PHAssetCollection(存放圖片集合的對象)
- 將圖片插入到相應的圖片集合中,完成全部操作。
下面的代碼部分是參考別人的,只不過個人將其封裝化,這樣就可以很方便的進行調用了。
對外的調用接口:
+ (void)saveImage:(UIImage *)image
{
//(1) 獲取當前的授權狀態(tài)
PHAuthorizationStatus lastStatus = [PHPhotoLibrary authorizationStatus];
//(2) 請求授權
[PHPhotoLibrary requestAuthorization:^(PHAuthorizationStatus status) {
//回到主線程
dispatch_async(dispatch_get_main_queue(), ^{
if(status == PHAuthorizationStatusDenied) //用戶拒絕(可能是之前拒絕的,有可能是剛才在系統彈框中選擇的拒絕)
{
if (lastStatus == PHAuthorizationStatusNotDetermined) {
//說明,用戶之前沒有做決定,在彈出授權框中,選擇了拒絕
[MBProgressHUD showError:@"保存失敗"];
return;
}
// 說明,之前用戶選擇拒絕過,現在又點擊保存按鈕,說明想要使用該功能,需要提示用戶打開授權
[MBProgressHUD showMessage:@"失敗!請在系統設置中開啟訪問相冊權限"];
}
else if(status == PHAuthorizationStatusAuthorized) //用戶允許
{
//保存圖片---調用上面封裝的方法
[self saveImageToCustomAblumWithImage:image];
}
else if (status == PHAuthorizationStatusRestricted)
{
[MBProgressHUD showError:@"系統原因,無法訪問相冊"];
}
});
}];
}
至于MBProgressHUD,可以在相應的GitHub自行下載。
+ (void)saveImageToCustomAblumWithImage:(UIImage *)image
{
//1 將圖片保存到系統的【相機膠卷】中---調用剛才的方法
PHFetchResult<PHAsset *> *assets = [self syncSaveImageWithPhotos:image];
if (assets == nil)
{
[MBProgressHUD showError:@"保存失敗"];
return;
}
//2 擁有自定義相冊(與 APP 同名,如果沒有則創(chuàng)建)--調用剛才的方法
PHAssetCollection *assetCollection = [self getAssetCollectionWithAppNameAndCreateIfNo];
if (assetCollection == nil) {
[MBProgressHUD showError:@"相冊創(chuàng)建失敗"];
return;
}
//3 將剛才保存到相機膠卷的圖片添加到自定義相冊中 --- 保存帶自定義相冊--屬于增的操作,需要在PHPhotoLibrary的block中進行
NSError *error = nil;
[[PHPhotoLibrary sharedPhotoLibrary] performChangesAndWait:^{
//--告訴系統,要操作哪個相冊
PHAssetCollectionChangeRequest *collectionChangeRequest = [PHAssetCollectionChangeRequest changeRequestForAssetCollection:assetCollection];
//--添加圖片到自定義相冊--追加--就不能成為封面了
//--[collectionChangeRequest addAssets:assets];
//--插入圖片到自定義相冊--插入--可以成為封面
[collectionChangeRequest insertAssets:assets atIndexes:[NSIndexSet indexSetWithIndex:0]];
} error:&error];
if (error) {
[MBProgressHUD showError:@"保存失敗"];
return;
}
[MBProgressHUD showSuccess:@"保存成功"];
}
+ (PHFetchResult<PHAsset *> *)syncSaveImageWithPhotos:(UIImage *)image
{
//--1 創(chuàng)建 ID 這個參數可以獲取到圖片保存后的 asset對象
__block NSString *createdAssetID = nil;
//--2 保存圖片
NSError *error = nil;
[[PHPhotoLibrary sharedPhotoLibrary] performChangesAndWait:^{
//----block 執(zhí)行的時候還沒有保存成功--獲取占位圖片的 id,通過 id 獲取圖片---同步
createdAssetID = [PHAssetChangeRequest creationRequestForAssetFromImage:image].placeholderForCreatedAsset.localIdentifier;
} error:&error];
//--3 如果失敗,則返回空
if (error) {
return nil;
}
//--4 成功后,返回對象
//獲取保存到系統相冊成功后的 asset 對象集合,并返回
PHFetchResult<PHAsset *> *assets = [PHAsset fetchAssetsWithLocalIdentifiers:@[createdAssetID] options:nil];
return assets;
}
+ (PHAssetCollection *)getAssetCollectionWithAppNameAndCreateIfNo
{
//1 獲取以 APP 的名稱
NSDictionary *infoDictionary = [[NSBundle mainBundle] infoDictionary];
NSString *title = [infoDictionary objectForKey:@"CFBundleDisplayName"];
//2 獲取與 APP 同名的自定義相冊
PHFetchResult<PHAssetCollection *> *collections = [PHAssetCollection fetchAssetCollectionsWithType:PHAssetCollectionTypeAlbum subtype:PHAssetCollectionSubtypeAlbumRegular options:nil];
for (PHAssetCollection *collection in collections) {
//遍歷
if ([collection.localizedTitle isEqualToString:title]) {
//找到了同名的自定義相冊--返回
return collection;
}
}
//說明沒有找到,需要創(chuàng)建
NSError *error = nil;
__block NSString *createID = nil; //用來獲取創(chuàng)建好的相冊
[[PHPhotoLibrary sharedPhotoLibrary] performChangesAndWait:^{
//發(fā)起了創(chuàng)建新相冊的請求,并拿到ID,當前并沒有創(chuàng)建成功,待創(chuàng)建成功后,通過 ID 來獲取創(chuàng)建好的自定義相冊
PHAssetCollectionChangeRequest *request = [PHAssetCollectionChangeRequest creationRequestForAssetCollectionWithTitle:title];
createID = request.placeholderForCreatedAssetCollection.localIdentifier;
} error:&error];
if (error) {
[MBProgressHUD showError:@"創(chuàng)建失敗"];
return nil;
}else{
[MBProgressHUD showSuccess:@"創(chuàng)建成功"];
//通過 ID 獲取創(chuàng)建完成的相冊 -- 是一個數組
return [PHAssetCollection fetchAssetCollectionsWithLocalIdentifiers:@[createID] options:nil].firstObject;
}
}
這樣圖片就會以app的名稱形式儲存到本地的相冊中。