iOS系統(tǒng)相冊基本操作

一、前言####

在iOS8以前,我們操作系統(tǒng)相冊,一般使用<AssetsLibrary/AssetsLibrary.h>庫進行操作,iOS8以后,Apple推出了<Photos/Photos.h>庫,以提升操作系統(tǒng)相冊的效率。針對目前iOS8及以上用戶占有率已超過95%,本文將采用<Photos/Photos.h>庫進行開發(fā)說明。

二、針對系統(tǒng)相冊的操作####

思路:為了滿足保存視頻/圖片到系統(tǒng)相冊指定路徑,并隨時準備刪除的變態(tài)需求,首先得弄清<Photos/Photos.h>庫,保存一般都好說,但是想刪除系統(tǒng)相冊中的某個圖片或者視頻,第一印象就根據(jù)保存的文件名來進行刪除,可是使用過該api之后,發(fā)現(xiàn)存在系統(tǒng)相冊之后的名字根本就不是你原來存的那個名字,fileName也沒有對外提供給你使用,但是它提供了localIdentifier字段,用來唯一標識系統(tǒng)相冊中的元素,那么事情就好辦了,我們在進行保存圖片或者視頻的時候,將其localIdentifier緩存到一個plist文件中,然后每次刪除的時候,通過對應(yīng)的文件名找到相應(yīng)的localIdentifier就可以進行刪除了。

  • 判斷系統(tǒng)相冊中是否存在該指定的文件夾
- (BOOL)isExistFolder:(NSString *)folderName {
    //首先獲取用戶手動創(chuàng)建相冊的集合
    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;
}
  • 在系統(tǒng)相冊中創(chuàng)建指定的文件夾
- (void)createFolder:(NSString *)folderName {
    if (![self isExistFolder:folderName]) {
        [[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{
            //添加HUD文件夾
            [PHAssetCollectionChangeRequest creationRequestForAssetCollectionWithTitle:folderName];
            
        } completionHandler:^(BOOL success, NSError * _Nullable error) {
            if (success) {
                NSLog(@"創(chuàng)建相冊文件夾成功!");
            } else {
                NSLog(@"創(chuàng)建相冊文件夾失敗:%@", error);
            }
        }];
    }
}
  • 保存圖片到系統(tǒng)相冊指定目錄
- (void)saveImagePath:(NSString *)imagePath{
    NSURL *url = [NSURL fileURLWithPath:imagePath];
    
    //標識保存到系統(tǒng)相冊中的標識
    __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:^{
                //請求創(chuàng)建一個Asset
                PHAssetChangeRequest *assetRequest = [PHAssetChangeRequest creationRequestForAssetFromImageAtFileURL:url];
                //請求編輯相冊
                PHAssetCollectionChangeRequest *collectonRequest = [PHAssetCollectionChangeRequest changeRequestForAssetCollection:assetCollection];
                //為Asset創(chuàng)建一個占位符,放到相冊編輯請求中
                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);
                }
            }];
        }
    }];
}
  • 保存視頻到系統(tǒng)相冊指定目錄

- (void)saveVideoPath:(NSString *)videoPath {
    NSURL *url = [NSURL fileURLWithPath:videoPath];
    
    //標識保存到系統(tǒng)相冊中的標識
    __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:^{
                //請求創(chuàng)建一個Asset
                PHAssetChangeRequest *assetRequest = [PHAssetChangeRequest creationRequestForAssetFromVideoAtFileURL:url];
                //請求編輯相冊
                PHAssetCollectionChangeRequest *collectonRequest = [PHAssetCollectionChangeRequest changeRequestForAssetCollection:assetCollection];
                //為Asset創(chuàng)建一個占位符,放到相冊編輯請求中
                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);
                }
            }];
        }
    }];
}
  • 刪除系統(tǒng)相冊指定目錄下的文件
- (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);
                            }
                        }];
                    }
                }];
            }
        }];
    }
}
下面給出具體的實現(xiàn)代碼:######

頭文件定義如下:

#import <Foundation/Foundation.h>

@interface YQAssetOperator : NSObject

/**
 *  初始化方法
 *
 *  @param folderName 操作的目錄文件
 *
 *  @return 操作對象
 */
- (instancetype)initWithFolderName:(NSString *)folderName;

/**
 *  保存圖片到系統(tǒng)相冊
 *
 *  @param imagePath  保存的圖片路徑
 *  @param folderName 目的文件的路徑
 */
- (void)saveImagePath:(NSString *)imagePath;

/**
 *  保存視頻到系統(tǒng)相冊
 *
 *  @param videoPath  保存的視頻路徑
 *  @param folderName 目的文件的路徑
 */
- (void)saveVideoPath:(NSString *)videoPath;

/**
 *  刪除系統(tǒng)相冊中的文件
 *
 *  @param filePath   文件的路徑
 *  @param folderName 文件夾的名字
 */
- (void)deleteFile:(NSString *)filePath;

@end

實現(xiàn)文件:

#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];
    
    //標識保存到系統(tǒng)相冊中的標識
    __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:^{
                //請求創(chuàng)建一個Asset
                PHAssetChangeRequest *assetRequest = [PHAssetChangeRequest creationRequestForAssetFromImageAtFileURL:url];
                //請求編輯相冊
                PHAssetCollectionChangeRequest *collectonRequest = [PHAssetCollectionChangeRequest changeRequestForAssetCollection:assetCollection];
                //為Asset創(chuàng)建一個占位符,放到相冊編輯請求中
                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];
    
    //標識保存到系統(tǒng)相冊中的標識
    __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:^{
                //請求創(chuàng)建一個Asset
                PHAssetChangeRequest *assetRequest = [PHAssetChangeRequest creationRequestForAssetFromVideoAtFileURL:url];
                //請求編輯相冊
                PHAssetCollectionChangeRequest *collectonRequest = [PHAssetCollectionChangeRequest changeRequestForAssetCollection:assetCollection];
                //為Asset創(chuàng)建一個占位符,放到相冊編輯請求中
                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 {
    //首先獲取用戶手動創(chuàng)建相冊的集合
    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(@"創(chuàng)建相冊文件夾成功!");
            } else {
                NSLog(@"創(chuàng)建相冊文件夾失敗:%@", error);
            }
        }];
    }
}

#pragma mark - setters和getters
- (void)setFolderName:(NSString *)folderName {
    if (!_folderName) {
        _folderName = folderName;
        [self createFolder:folderName];
    }
}

- (void)setPlistName:(NSString *)plistName {
    if (!_plistName) {
        _plistName = plistName;
        
        //創(chuàng)建plist文件,記錄path和localIdentifier的對應(yīng)關(guān)系
        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(@"創(chuàng)建plist文件失敗!");
            } else {
                NSLog(@"創(chuàng)建plist文件成功!");
            }
        } else {
            NSLog(@"沙盒中已有該plist文件,無需創(chuàng)建!");
        }
    }
}

#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 - 根據(jù)路徑獲取文件名
- (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

測試程序?qū)⒁粋€二維碼圖片和一段視頻存入了"LOVE"文件夾中,效果圖如下:

效果圖

源碼地址:https://github.com/GitterYang/YQSystemPhotoOperation

如有什么疑問或者文中有不當(dāng)之處,請指出,謝謝。祝大家好夢!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 發(fā)現(xiàn) 關(guān)注 消息 iOS 第三方庫、插件、知名博客總結(jié) 作者大灰狼的小綿羊哥哥關(guān)注 2017.06.26 09:4...
    肇東周閱讀 15,099評論 4 61
  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 178,828評論 25 709
  • 不約大醉俠閱讀 198評論 0 0
  • 背叛與罪惡,黑夜與半天,孤獨與寂寞,殘忍與決絕…… 桐原亮司死時,雪穗說:“我不認識他。” 一句話,將整本書的氛圍...
    秋之雨閱讀 312評論 0 1

友情鏈接更多精彩內(nèi)容