####一、前言####
在iOS8以前,我們作業系統相簿,一般使用<AssetsLibrary/AssetsLibrary.h>
庫進行操作,iOS8以後,Apple推出了<Photos/Photos.h>
庫,以提升作業系統相簿的效率。針對目前iOS8及以上使用者佔有率已超過95%,本文將採用<Photos/Photos.h>
庫進行開發說明。
####二、針對系統相簿的操作####
思路:為了滿足儲存視訊/圖片到系統相簿指定路徑,並隨時準備刪除的變態需求,首先得弄清
<Photos/Photos.h>
庫,儲存一般都好說,但是想刪除系統相簿中的某個圖片或者視訊,第一印象就根據儲存的檔名來進行刪除,可是使用過該api之後,發現存在系統相簿之後的名字根本就不是你原來存的那個名字,fileName也沒有對外提供給你使用,但是它提供了localIdentifier
欄位,用來唯一標識系統相簿中的元素,那麼事情就好辦了,我們在進行儲存圖片或者視訊的時候,將其localIdentifier
快取到一個plist
檔案中,然後每次刪除的時候,通過對應的檔名找到相應的localIdentifier
就可以進行刪除了。
- 判斷系統相簿中是否存在該指定的資料夾
- (BOOL)isExistFolder:(NSString *)folderName {
//首先獲取使用者手動建立相簿的集合
PHFetchResult *collectonResuts = [PHCollectionList fetchTopLevelUserCollectionsWithOptions:nil];
__block BOOL isExisted = NO;
//對獲取到集合進行遍歷
[collectonResuts enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
PHAssetCollection *assetCollection = obj;
//folderName是我們寫入照片的相簿
if ([assetCollection.localizedTitle isEqualToString:folderName]) {
isExisted = YES;
}
}];
return isExisted;
}
複製程式碼
- 在系統相簿中建立指定的資料夾
- (void)createFolder:(NSString *)folderName {
if (![self isExistFolder:folderName]) {
[[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{
//新增HUD資料夾
[PHAssetCollectionChangeRequest creationRequestForAssetCollectionWithTitle:folderName];
} completionHandler:^(BOOL success, NSError * _Nullable error) {
if (success) {
NSLog(@"建立相簿資料夾成功!");
} else {
NSLog(@"建立相簿資料夾失敗:%@", error);
}
}];
}
}
複製程式碼
- 儲存圖片到系統相簿指定目錄
- (void)saveImagePath:(NSString *)imagePath{
NSURL *url = [NSURL fileURLWithPath:imagePath];
//標識儲存到系統相簿中的標識
__block NSString *localIdentifier;
//首先獲取相簿的集合
PHFetchResult *collectonResuts = [PHCollectionList fetchTopLevelUserCollectionsWithOptions:nil];
//對獲取到集合進行遍歷
[collectonResuts enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
PHAssetCollection *assetCollection = obj;
//Camera Roll是我們寫入照片的相簿
if ([assetCollection.localizedTitle isEqualToString:_folderName]) {
[[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{
//請求建立一個Asset
PHAssetChangeRequest *assetRequest = [PHAssetChangeRequest creationRequestForAssetFromImageAtFileURL:url];
//請求編輯相簿
PHAssetCollectionChangeRequest *collectonRequest = [PHAssetCollectionChangeRequest changeRequestForAssetCollection:assetCollection];
//為Asset建立一個佔位符,放到相簿編輯請求中
PHObjectPlaceholder *placeHolder = [assetRequest placeholderForCreatedAsset];
//相簿中新增照片
[collectonRequest addAssets:@[placeHolder]];
localIdentifier = placeHolder.localIdentifier;
} completionHandler:^(BOOL success, NSError *error) {
if (success) {
NSLog(@"儲存圖片成功!");
NSMutableDictionary *dict = [NSMutableDictionary dictionaryWithDictionary:[self readFromPlist]];
[dict setObject:localIdentifier forKey:[self showFileNameFromPath:imagePath]];
[self writeDicToPlist:dict];
} else {
NSLog(@"儲存圖片失敗:%@", error);
}
}];
}
}];
}
複製程式碼
- 儲存視訊到系統相簿指定目錄
- (void)saveVideoPath:(NSString *)videoPath {
NSURL *url = [NSURL fileURLWithPath:videoPath];
//標識儲存到系統相簿中的標識
__block NSString *localIdentifier;
//首先獲取相簿的集合
PHFetchResult *collectonResuts = [PHCollectionList fetchTopLevelUserCollectionsWithOptions:nil];
//對獲取到集合進行遍歷
[collectonResuts enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
PHAssetCollection *assetCollection = obj;
//folderName是我們寫入照片的相簿
if ([assetCollection.localizedTitle isEqualToString:_folderName]) {
[[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{
//請求建立一個Asset
PHAssetChangeRequest *assetRequest = [PHAssetChangeRequest creationRequestForAssetFromVideoAtFileURL:url];
//請求編輯相簿
PHAssetCollectionChangeRequest *collectonRequest = [PHAssetCollectionChangeRequest changeRequestForAssetCollection:assetCollection];
//為Asset建立一個佔位符,放到相簿編輯請求中
PHObjectPlaceholder *placeHolder = [assetRequest placeholderForCreatedAsset];
//相簿中新增視訊
[collectonRequest addAssets:@[placeHolder]];
localIdentifier = placeHolder.localIdentifier;
} completionHandler:^(BOOL success, NSError *error) {
if (success) {
NSLog(@"儲存視訊成功!");
NSMutableDictionary *dict = [NSMutableDictionary dictionaryWithDictionary:[self readFromPlist]];
[dict setObject:localIdentifier forKey:[self showFileNameFromPath:videoPath]];
[self writeDicToPlist:dict];
} else {
NSLog(@"儲存視訊失敗:%@", error);
}
}];
}
}];
}
複製程式碼
- 刪除系統相簿指定目錄下的檔案
- (void)deleteFile:(NSString *)filePath {
if ([self isExistFolder:_folderName]) {
//獲取需要刪除檔案的localIdentifier
NSDictionary *dict = [self readFromPlist];
NSString *localIdentifier = [dict valueForKey:[self showFileNameFromPath:filePath]];
PHFetchResult *collectonResuts = [PHCollectionList fetchTopLevelUserCollectionsWithOptions:nil];
[collectonResuts enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
PHAssetCollection *assetCollection = obj;
if ([assetCollection.localizedTitle isEqualToString:_folderName]) {
PHFetchResult *assetResult = [PHAsset fetchAssetsInAssetCollection:assetCollection options:[PHFetchOptions new]];
[assetResult enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
PHAsset *asset = obj;
if ([localIdentifier isEqualToString:asset.localIdentifier]) {
[[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{
[PHAssetChangeRequest deleteAssets:@[obj]];
} completionHandler:^(BOOL success, NSError *error) {
if (success) {
NSLog(@"刪除成功!");
NSMutableDictionary *updateDic = [NSMutableDictionary dictionaryWithDictionary:dict];
[updateDic removeObjectForKey:[self showFileNameFromPath:filePath]];
[self writeDicToPlist:updateDic];
} else {
NSLog(@"刪除失敗:%@", error);
}
}];
}
}];
}
}];
}
}
複製程式碼
######下面給出具體的實現程式碼:######
標頭檔案定義如下:
#import <Foundation/Foundation.h>
@interface YQAssetOperator : NSObject
/**
* 初始化方法
*
* @param folderName 操作的目錄檔案
*
* @return 操作物件
*/
- (instancetype)initWithFolderName:(NSString *)folderName;
/**
* 儲存圖片到系統相簿
*
* @param imagePath 儲存的圖片路徑
* @param folderName 目的檔案的路徑
*/
- (void)saveImagePath:(NSString *)imagePath;
/**
* 儲存視訊到系統相簿
*
* @param videoPath 儲存的視訊路徑
* @param folderName 目的檔案的路徑
*/
- (void)saveVideoPath:(NSString *)videoPath;
/**
* 刪除系統相簿中的檔案
*
* @param filePath 檔案的路徑
* @param folderName 資料夾的名字
*/
- (void)deleteFile:(NSString *)filePath;
@end
複製程式碼
實現檔案:
#import "YQAssetOperator.h"
#import <Photos/Photos.h>
@interface YQAssetOperator ()
@property (nonatomic, copy) NSString *plistName;
@property (nonatomic, copy) NSString *folderName;
@end
@implementation YQAssetOperator
- (instancetype)initWithFolderName:(NSString *)folderName {
self = [self init];
if (self) {
self.plistName = @"Asset";
self.folderName = folderName;
}
return self;
}
- (void)saveImagePath:(NSString *)imagePath{
NSURL *url = [NSURL fileURLWithPath:imagePath];
//標識儲存到系統相簿中的標識
__block NSString *localIdentifier;
//首先獲取相簿的集合
PHFetchResult *collectonResuts = [PHCollectionList fetchTopLevelUserCollectionsWithOptions:nil];
//對獲取到集合進行遍歷
[collectonResuts enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
PHAssetCollection *assetCollection = obj;
//Camera Roll是我們寫入照片的相簿
if ([assetCollection.localizedTitle isEqualToString:_folderName]) {
[[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{
//請求建立一個Asset
PHAssetChangeRequest *assetRequest = [PHAssetChangeRequest creationRequestForAssetFromImageAtFileURL:url];
//請求編輯相簿
PHAssetCollectionChangeRequest *collectonRequest = [PHAssetCollectionChangeRequest changeRequestForAssetCollection:assetCollection];
//為Asset建立一個佔位符,放到相簿編輯請求中
PHObjectPlaceholder *placeHolder = [assetRequest placeholderForCreatedAsset];
//相簿中新增照片
[collectonRequest addAssets:@[placeHolder]];
localIdentifier = placeHolder.localIdentifier;
} completionHandler:^(BOOL success, NSError *error) {
if (success) {
NSLog(@"儲存圖片成功!");
NSMutableDictionary *dict = [NSMutableDictionary dictionaryWithDictionary:[self readFromPlist]];
[dict setObject:localIdentifier forKey:[self showFileNameFromPath:imagePath]];
[self writeDicToPlist:dict];
} else {
NSLog(@"儲存圖片失敗:%@", error);
}
}];
}
}];
}
- (void)saveVideoPath:(NSString *)videoPath {
NSURL *url = [NSURL fileURLWithPath:videoPath];
//標識儲存到系統相簿中的標識
__block NSString *localIdentifier;
//首先獲取相簿的集合
PHFetchResult *collectonResuts = [PHCollectionList fetchTopLevelUserCollectionsWithOptions:nil];
//對獲取到集合進行遍歷
[collectonResuts enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
PHAssetCollection *assetCollection = obj;
//folderName是我們寫入照片的相簿
if ([assetCollection.localizedTitle isEqualToString:_folderName]) {
[[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{
//請求建立一個Asset
PHAssetChangeRequest *assetRequest = [PHAssetChangeRequest creationRequestForAssetFromVideoAtFileURL:url];
//請求編輯相簿
PHAssetCollectionChangeRequest *collectonRequest = [PHAssetCollectionChangeRequest changeRequestForAssetCollection:assetCollection];
//為Asset建立一個佔位符,放到相簿編輯請求中
PHObjectPlaceholder *placeHolder = [assetRequest placeholderForCreatedAsset];
//相簿中新增視訊
[collectonRequest addAssets:@[placeHolder]];
localIdentifier = placeHolder.localIdentifier;
} completionHandler:^(BOOL success, NSError *error) {
if (success) {
NSLog(@"儲存視訊成功!");
NSMutableDictionary *dict = [NSMutableDictionary dictionaryWithDictionary:[self readFromPlist]];
[dict setObject:localIdentifier forKey:[self showFileNameFromPath:videoPath]];
[self writeDicToPlist:dict];
} else {
NSLog(@"儲存視訊失敗:%@", error);
}
}];
}
}];
}
- (void)deleteFile:(NSString *)filePath {
if ([self isExistFolder:_folderName]) {
//獲取需要刪除檔案的localIdentifier
NSDictionary *dict = [self readFromPlist];
NSString *localIdentifier = [dict valueForKey:[self showFileNameFromPath:filePath]];
PHFetchResult *collectonResuts = [PHCollectionList fetchTopLevelUserCollectionsWithOptions:nil];
[collectonResuts enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
PHAssetCollection *assetCollection = obj;
if ([assetCollection.localizedTitle isEqualToString:_folderName]) {
PHFetchResult *assetResult = [PHAsset fetchAssetsInAssetCollection:assetCollection options:[PHFetchOptions new]];
[assetResult enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
PHAsset *asset = obj;
if ([localIdentifier isEqualToString:asset.localIdentifier]) {
[[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{
[PHAssetChangeRequest deleteAssets:@[obj]];
} completionHandler:^(BOOL success, NSError *error) {
if (success) {
NSLog(@"刪除成功!");
NSMutableDictionary *updateDic = [NSMutableDictionary dictionaryWithDictionary:dict];
[updateDic removeObjectForKey:[self showFileNameFromPath:filePath]];
[self writeDicToPlist:updateDic];
} else {
NSLog(@"刪除失敗:%@", error);
}
}];
}
}];
}
}];
}
}
- (BOOL)isExistFolder:(NSString *)folderName {
//首先獲取使用者手動建立相簿的集合
PHFetchResult *collectonResuts = [PHCollectionList fetchTopLevelUserCollectionsWithOptions:nil];
__block BOOL isExisted = NO;
//對獲取到集合進行遍歷
[collectonResuts enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
PHAssetCollection *assetCollection = obj;
//folderName是我們寫入照片的相簿
if ([assetCollection.localizedTitle isEqualToString:folderName]) {
isExisted = YES;
}
}];
return isExisted;
}
- (void)createFolder:(NSString *)folderName {
if (![self isExistFolder:folderName]) {
[[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{
//新增HUD資料夾
[PHAssetCollectionChangeRequest creationRequestForAssetCollectionWithTitle:folderName];
} completionHandler:^(BOOL success, NSError * _Nullable error) {
if (success) {
NSLog(@"建立相簿資料夾成功!");
} else {
NSLog(@"建立相簿資料夾失敗:%@", error);
}
}];
}
}
#pragma mark - setters和getters
- (void)setFolderName:(NSString *)folderName {
if (!_folderName) {
_folderName = folderName;
[self createFolder:folderName];
}
}
- (void)setPlistName:(NSString *)plistName {
if (!_plistName) {
_plistName = plistName;
//建立plist檔案,記錄path和localIdentifier的對應關係
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask,YES);
NSString *path = [paths objectAtIndex:0];
NSString *filePath = [path stringByAppendingPathComponent:[NSString stringWithFormat:@"%@.plist", plistName]];
NSLog(@"plist路徑:%@", filePath);
NSFileManager* fm = [NSFileManager defaultManager];
if (![fm fileExistsAtPath:filePath]) {
BOOL success = [fm createFileAtPath:filePath contents:nil attributes:nil];
if (!success) {
NSLog(@"建立plist檔案失敗!");
} else {
NSLog(@"建立plist檔案成功!");
}
} else {
NSLog(@"沙盒中已有該plist檔案,無需建立!");
}
}
}
#pragma mark - 寫入plist檔案
- (void)writeDicToPlist:(NSDictionary *)dict {
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask,YES);
NSString *path = [paths objectAtIndex:0];
NSString *filePath = [path stringByAppendingPathComponent:[NSString stringWithFormat:@"%@.plist", _plistName]];
[dict writeToFile:filePath atomically:YES];
}
#pragma mark - 讀取plist檔案
- (NSDictionary *)readFromPlist {
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask,YES);
NSString *path = [paths objectAtIndex:0];
NSString *filePath = [path stringByAppendingPathComponent:[NSString stringWithFormat:@"%@.plist", _plistName]];
return [NSDictionary dictionaryWithContentsOfFile:filePath];
}
#pragma mark - 根據路徑獲取檔名
- (NSString *)showFileNameFromPath:(NSString *)path {
return [NSString stringWithFormat:@"%@", [[path componentsSeparatedByString:@"/"] lastObject]];
}
@end
複製程式碼
測試程式:
#import "ViewController.h"
#import "YQAssetOperator.h"
@interface ViewController (){
YQAssetOperator *_assetOperator;
}
- (IBAction)deleteFile:(UIButton *)sender;
- (IBAction)addFiles:(UIButton *)sender;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = [UIColor grayColor];
_assetOperator = [[YQAssetOperator alloc] initWithFolderName:@"LOVE"];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (IBAction)deleteFile:(UIButton *)sender {
NSString *videoPath =[[NSBundle mainBundle] pathForResource:@"0425_103546" ofType:@"mp4"];
[_assetOperator deleteFile:videoPath];
}
- (IBAction)addFiles:(UIButton *)sender {
//儲存圖片
NSString *imagePath =[[NSBundle mainBundle] pathForResource:@"scanner" ofType:@"png"];
[_assetOperator saveImagePath:imagePath];
//儲存視訊
NSString *videoPath =[[NSBundle mainBundle] pathForResource:@"0425_103546" ofType:@"mp4"];
[_assetOperator saveVideoPath:videoPath];
}
@end
複製程式碼
測試程式將一個二維碼圖片和一段視訊存入了"LOVE"資料夾中,效果圖如下:
原始碼地址:github.com/GitterYang/…
如有什麼疑問或者文中有不當之處,請指出,謝謝。祝大家好夢!