在APP中點擊照片,都會顯示出大圖,然后在大圖的上面會有個保存照片的按鈕,照片直接保存到了系統(tǒng)的【相機膠卷】相冊中,但是因為公司產(chǎn)品的需要,我們需要創(chuàng)建和APP同名的相冊保存在【自定義相冊】里面,這也就是分應(yīng)用存儲,因為用戶可能從QQ,微信,微博分別存儲,下次用戶想找某個應(yīng)用的圖片,直接點開該應(yīng)用相冊即可,提高用戶體驗。
注意:
【自定義相冊】里面的圖片來源于【相機膠卷】相冊中,即:【相機膠卷】引用【自定義相冊】, 如果用戶刪掉【相機膠卷】里面的圖片, 那么【自定義相冊】重的圖片也會刪掉。但是,如果用戶刪掉【自定義相冊】里面的圖片, 那么【相機膠卷】中依然有該圖片。
開發(fā)步驟:
- 1.先保存圖片到【相機膠卷】(不能直接保存到自定義相冊中)
- 2.擁有一個【自定義相冊】
- 3.將剛才保存到【相機膠卷】里面的圖片引用到【自定義相冊】
方法1:用C語言函數(shù)實現(xiàn)
將圖片保存到系統(tǒng)的相冊中,只需要下面兩句代碼就搞定了
//參數(shù)1:圖片對象
//參數(shù)2:成功方法綁定的target
//參數(shù)3:成功后調(diào)用方法
//參數(shù)4:需要傳遞信息(成功后調(diào)用方法的參數(shù))
UIImageWriteToSavedPhotosAlbum(self.imageView.image, self, @selector(image:didFinishSavingWithError:contextInfo:), nil);
#pragma mark -- <保存到相冊>
-(void)image:(UIImage *)image didFinishSavingWithError:(NSError *)error contextInfo:(void *)contextInfo {
NSString *msg = nil ;
if(error){
msg = @"保存圖片失敗" ;
}else{
msg = @"保存圖片成功" ;
}
}
注意:UIImageWriteToSavedPhotosAlbum方法必須實現(xiàn)圖1的代理方法,否則會崩潰。

界面效果如下:界面圖

方法2:使用Photos框架實現(xiàn)
2.1 Photos01-基本認識
PHAsset : 一個PHAsset對象就代表相冊中的一張圖片或者一個視頻
PHAssetCollection : 一個PHAssetCollection 對象就代表一個相冊
如果我們想保存圖片到【相機膠卷】,首先要保證添加一個新的PHAsset對象,那么如何操作這些對象呢?無非是對這些對象進行增刪改查。
PHAsset
一個PHAsset對象就代表相冊中的一張圖片或者一個視頻
增刪改 PHAssetChangeRequest 包括圖片/視頻相關(guān)的改動操作查 [PHAsset fetchAssets...];
PHAssetCollection
一個PHAssetCollection 對象就代表一個相冊增刪改 PHAssetCollectionChangeRequest 包括相冊相關(guān)的所有改動操作
查
[PHAssetCollection fetchAssetCollectionsContainingAsset:...];
2.2 Photos02-保存圖片到相機膠卷
//保存圖片到【相機膠卷】
/// 異步執(zhí)行修改操作
[[PHPhotoLibrary sharedPhotoLibrary]performChanges:^{
[PHAssetChangeRequest creationRequestForAssetFromImage:self.imageView.image];
} completionHandler:^(BOOL success, NSError * _Nullable error) {
if (error) {
NSLog(@"%@",@"保存失敗");
} else {
NSLog(@"%@",@"保存成功");
}
}];
效果如圖2 圖3所示


Tips:
如果直接使用 [PHAssetChangeRequest creationRequestForAssetFromImage:self.imageView.image]; 則會出現(xiàn)如下的崩潰信息
reason: 'This method can only be called from inside of -[PHPhotoLibrary performChanges:completionHandler:] or -[PHPhotoLibrary performChangesAndWait:error:]'
結(jié)論:凡是涉及增刪改的操作,均需要放在performChanges里面執(zhí)行。
[[PHPhotoLibrary sharedPhotoLibrary]performChanges:^{
// 這里執(zhí)行操作
} completionHandler:^(BOOL success, NSError * _Nullable error) {
}];
2.3 Photos03-創(chuàng)建新的相冊
NSError *error = nil;
[[PHPhotoLibrary sharedPhotoLibrary]performChangesAndWait:^{
//獲取app名字
NSString *title = [NSBundle mainBundle].infoDictionary[(__bridge NSString*)kCFBundleNameKey];
//創(chuàng)建一個【自定義相冊】
[PHAssetCollectionChangeRequest creationRequestForAssetCollectionWithTitle:title];
} error:&error];
效果如圖4:

Tips:如果我們一直點擊保存圖片按鈕,則會出現(xiàn)重復(fù)創(chuàng)建多個相冊的問題:
如圖5所示

接著我們來解決這個問題。
2.4 Photos04-查詢相冊
NSString *title = [NSBundle mainBundle].infoDictionary[(__bridge NSString*)kCFBundleNameKey];
//查詢所有【自定義相冊】
PHFetchResult<PHAssetCollection *> *collections = [PHAssetCollection fetchAssetCollectionsWithType:PHAssetCollectionTypeAlbum subtype:PHAssetCollectionSubtypeAlbumRegular options:nil];
PHAssetCollection *createCollection = nil;
for (PHAssetCollection *collection in collections) {
if ([collection.localizedTitle isEqualToString:title]) {
createCollection = collection;
break;
}
}
if (createCollection == nil) {
//當(dāng)前對應(yīng)的app相冊沒有被創(chuàng)建
//創(chuàng)建一個【自定義相冊】
NSError *error = nil;
[[PHPhotoLibrary sharedPhotoLibrary]performChangesAndWait:^{
//創(chuàng)建一個【自定義相冊】
[PHAssetCollectionChangeRequest creationRequestForAssetCollectionWithTitle:title];
} error:&error];
}
輸出結(jié)果:
此時,無論你點擊多少次,均只會創(chuàng)建一個與APP同名的相冊。
Tips: 如果我們想把圖片保存到【自定義相冊】里面的話,必須拿到相冊對象,但是細心地你此時可能會發(fā)現(xiàn),如果是第一次創(chuàng)建相冊(即:相冊中沒有與APP同名的相冊),
createCollection對象會為nil,所以我們還需要優(yōu)化創(chuàng)建【自定義相冊】的代碼。
核心代碼:
if (createCollection == nil) {
//當(dāng)前對應(yīng)的app相冊沒有被創(chuàng)建
//創(chuàng)建一個【自定義相冊】
NSError *error = nil;
__block NSString *createCollectionID = nil;
[[PHPhotoLibrary sharedPhotoLibrary]performChangesAndWait:^{
//創(chuàng)建一個【自定義相冊】
createCollectionID = [PHAssetCollectionChangeRequest creationRequestForAssetCollectionWithTitle:title].placeholderForCreatedAssetCollection.localIdentifier;
} error:&error];
createCollection = [PHAssetCollection fetchAssetCollectionsWithLocalIdentifiers:@[createCollectionID] options:nil].firstObject;
}
NSLog(@"%@",createCollection);
輸出結(jié)果:
2018-08-12 12:31:59.198751+0800 SavePhotoDemo[971:36240] <PHAssetCollection: 0x7fde6dc33960> 7C7FBA58-54AA-4320-9B2A-593BB75428FB/L0/040, title:"SavePhotoDemo", subtitle:"(null)" assetCollectionType=1/2
2.5 Photos05-保存圖片到自定義相冊
我們創(chuàng)建完相冊之后,需要將【相機膠卷】中的圖片放到【自定義相冊】里面去。
核心代碼如下:
// 1.先保存圖片到【相機膠卷】
/// 同步執(zhí)行修改操作
NSError *error = nil;
__block PHObjectPlaceholder *placeholder = nil;
[[PHPhotoLibrary sharedPhotoLibrary]performChangesAndWait:^{
placeholder = [PHAssetChangeRequest creationRequestForAssetFromImage:self.imageView.image].placeholderForCreatedAsset;
} error:&error];
if (error) {
NSLog(@"保存失敗");
return;
}
// 2.擁有一個【自定義相冊】
PHAssetCollection * assetCollection = self.createCollection;
if (assetCollection == nil) {
NSLog(@"創(chuàng)建相冊失敗");
}
// 3.將剛才保存到【相機膠卷】里面的圖片引用到【自定義相冊】
[[PHPhotoLibrary sharedPhotoLibrary]performChangesAndWait:^{
PHAssetCollectionChangeRequest *requtes = [PHAssetCollectionChangeRequest changeRequestForAssetCollection:assetCollection];
[requtes addAssets:@[placeholder]];
} error:&error];
if (error) {
NSLog(@"保存圖片失敗");
} else {
NSLog(@"保存圖片成功");
}
此時,我們點擊保存圖片到新建相冊~按鈕的時候,改圖片變被保存到【相機膠卷】和【自定義相冊】里面了。
如圖6所示

但是,此時你會發(fā)現(xiàn),每保存新的圖片,自定義相冊中均會添加到后面,那么如何把每次新添加的圖片前置呢?我們發(fā)現(xiàn)【相機膠卷】中每次新的圖片均會作為封面,系統(tǒng)自帶的這個比較智能,如圖圖7所示

所以修改添加圖片到相冊的代碼
// 3.將剛才保存到【相機膠卷】里面的圖片引用到【自定義相冊】
[[PHPhotoLibrary sharedPhotoLibrary]performChangesAndWait:^{
PHAssetCollectionChangeRequest *requtes = [PHAssetCollectionChangeRequest changeRequestForAssetCollection:assetCollection];
[requtes insertAssets:@[placeholder] atIndexes:[NSIndexSet indexSetWithIndex:0]];
} error:&error];
此時,【自定義相冊】中新添加的圖片便會作為相冊的封面了,效果如圖8所示。
