iOS 系統相冊的使用


使用的庫

ios8 以前,使用的是<AssetsLibrary/AssetsLibrary.h>,ios8以后,蘋果推出了<Photos/Photos.h> 現在一般使用photos庫

針對系統相冊的操作

文件處理思路,我們保存到系統相冊還比較好處理,但是刪除就有點麻煩了,因為我們存的文件名到了系統相冊名稱就已經變了,文件名也沒有對外提供,但是提供了一個localIdentifier的字段,用來標識相冊中的唯一元素,那么我們就需要將這個字段保存到plist或數據庫,通過對應關系找到就可以進行刪除了。

對相冊的任何改變操作,都應該在

- (void)performChanges:(dispatch_block_t)changeBlock completionHandler:(nullable void(^)(BOOL success, NSError *__nullable error))completionHandler;

的changeBlock方法內部做處理

請求相冊訪問權限

plist 中需要配置的key

  • NSPhotoLibraryUsageDescription --- Privacy - Photo Library Usage Description
typedef NS_ENUM(NSInteger, PHAuthorizationStatus) {
    PHAuthorizationStatusNotDetermined = 0,
          // 用戶還沒有對這個應用程序作出選擇
    PHAuthorizationStatusRestricted,        
        // 此應用程序未被授權訪問照片數據.用戶無法更改當前應用程序的狀態
    PHAuthorizationStatusDenied,            
        // 用戶明確拒絕了應用程序對照片數據的訪問。
    PHAuthorizationStatusAuthorized,        
        // 用戶已授權此應用程序訪問照片數據。
    PHAuthorizationStatusLimited API_AVAILABLE(ios(14)), 
        // 用戶已經授權使用有限的圖片庫.
        // 添加PHPhotoLibraryPreventAutomaticLimitedAccessAlert = YES到應用程序的信息。防止plist自動提醒用戶更新有限的庫選擇
        // 使用<PhotosUI/PHPhotoLibrary+PhotosUISupport.h>下的[PHPhotoLibrary(PhotosUISupport) presentLimitedLibraryPickerFromViewController:]來獲取有限的庫選擇器
};
+ (BOOL)requestPhotoPrivacy
{
    // 獲取授權狀態
    PHAuthorizationStatus status = [PHPhotoLibrary authorizationStatus];
    if (status == PHAuthorizationStatusDenied) {
        // 如果拒絕做對應彈框處理
        return NO;
    }
    return YES;
}

獲取當前的系統相冊列表

對應的相冊名

  • Favorites 收藏夾
  • Recents 最近
  • Recently Added 最近添加
  • Videos 視頻
  • Panoramas 全景照片
  • Time-lapse 延時攝影
  • Slo-mo 慢動作
  • Screenshots 截屏
  • Portrait 人像
  • Live Photos 實時照片
  • Selfies 自拍
  • Animated 動畫
  • Long Exposure 長曝光
  • Recently Deleted 最近刪除
PHFetchResult *smartAlbums = [PHAssetCollection fetchAssetCollectionsWithType:PHAssetCollectionTypeSmartAlbum subtype:PHAssetCollectionSubtypeAlbumRegular options:nil];
[smartAlbums enumerateObjectsUsingBlock:^(PHAssetCollection * _Nonnull collection, NSUInteger idx, BOOL * _Nonnull stop) {
    if ([collection isKindOfClass:[PHAssetCollection class]]) {
        PHFetchResult *fetchResult = [PHAsset fetchAssetsInAssetCollection:collection options:nil];
        
        NSLog(@"%@,count = %lu",collection.localizedTitle,(unsigned long)fetchResult.count);
    }
}];

判斷系統相冊是否存指定文件夾

- (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];
                // 設置創建時間
                assetRequest.creationDate = [NSDate date];
                //請求編輯相冊
                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)saveVideoToSystemMediaLibrary:(NSURL *)url AssetId:(NSString *)assetId {
    NSError *error = nil;

    BOOL result = [[PHPhotoLibrary sharedPhotoLibrary] performChangesAndWait:^{
        // 創建改變請求
        PHAssetChangeRequest *assetRequest = [PHAssetChangeRequest creationRequestForAssetFromVideoAtFileURL:url];
        assetRequest.creationDate = [NSDate date];
        PHObjectPlaceholder *placeHolder = [assetRequest placeholderForCreatedAsset];
        // 在數據庫中建立 自定義標識符和系統生成標識符關聯關系
        [self.dataBase saveLocalIdentifier:placeHolder.localIdentifier WithAssetsId:assetId];
    } error:&error];
    // 移除對應的資源文件
    [[NSFileManager defaultManager]removeItemAtURL:url error:nil];
    return result && !error;
}

- (BOOL)saveImageToSystemMediaLibrary:(NSURL *)url AssetId:(NSString *)assetId {
    // 判斷是否已經下載過對應的圖片資源
    if (![self isDonwloadWithAssetId:assetId]) {
        NSError *error = nil;
        BOOL result = [[PHPhotoLibrary sharedPhotoLibrary]performChangesAndWait:^{
            // 創建添加圖片請求
            PHAssetChangeRequest *assetRequest = [PHAssetChangeRequest creationRequestForAssetFromImageAtFileURL:url];
            assetRequest.creationDate = [NSDate date];
            PHObjectPlaceholder *placeHolder = [assetRequest placeholderForCreatedAsset];
            // 建立關聯關系
            [self.dataBase saveLocalIdentifier:placeHolder.localIdentifier WithAssetsId:assetId];
        } error:&error];
        // 移除對應的資源
        [[NSFileManager defaultManager]removeItemAtURL:url error:nil];
        return result && !error;
    } else {
        [[NSFileManager defaultManager]removeItemAtURL:url error:nil];
        return YES;
    }
}

- (BOOL)isDonwloadWithAssetId:(NSString *)assetId {
    // 獲取對應的標識符
    NSString *localIdentifier = [self.dataBase localIdentifierWithAssetId:assetId];
    if (!localIdentifier.length) {
        return NO;
    }
    // 查找是否存在對應的資源
    PHFetchResult *result = [PHAsset fetchAssetsWithLocalIdentifiers:@[localIdentifier] options:nil];
    if (result.count) {
        return YES;
    }
    return NO;
}

檢測當前資源是否為雲存儲

+ (void)checkSystemAssetInCloud:(PHAsset *)asset complet:(void(^)(BOOL isInCloud))complet {
    //視頻類型
    if (asset.mediaType == PHAssetMediaTypeVideo) {
        // 請求視頻資源
        [[PHImageManager defaultManager] requestExportSessionForVideo:asset options:nil exportPreset:AVAssetExportPresetHighestQuality resultHandler:^(AVAssetExportSession * _Nullable exportSession, NSDictionary * _Nullable info) {
            // 獲取的info中 PHImageResultIsInCloudKey 對應是否雲存儲
            dispatch_async(dispatch_get_main_queue(), ^{
                complet ? complet([info[PHImageResultIsInCloudKey] intValue] && !exportSession) : nil;
            });
        }];
    }
    
    // 圖片類型
    if (asset.mediaType == PHAssetMediaTypeImage) {
        // 創建圖片請求的option
        PHImageRequestOptions *originOptions = [[PHImageRequestOptions alloc]init];
        // 初始化相關的值
        originOptions.version = PHImageRequestOptionsVersionOriginal;
        originOptions.resizeMode = PHImageRequestOptionsResizeModeNone;
        originOptions.deliveryMode = PHImageRequestOptionsDeliveryModeHighQualityFormat;
        // ios 13之后
        if (@available(iOS 13, *)) {
            // 通過option請求圖片資源
            [[PHImageManager defaultManager]requestImageDataAndOrientationForAsset:asset options:originOptions resultHandler:^(NSData * _Nullable imageData, NSString * _Nullable dataUTI, CGImagePropertyOrientation orientation, NSDictionary * _Nullable info) {
                // 從info中獲取是否雲存儲值
                dispatch_async(dispatch_get_main_queue(), ^{
                    complet ? complet([info[PHImageResultIsInCloudKey] intValue] && !imageData) : nil;
                });
            }];
        } else {
            // 13之前 
            [[PHImageManager defaultManager]requestImageDataForAsset:asset options:originOptions resultHandler:^(NSData * _Nullable imageData, NSString * _Nullable dataUTI, UIImageOrientation orientation, NSDictionary * _Nullable info) {
                // 從info中獲取對應信息
                dispatch_async(dispatch_get_main_queue(), ^{
                    complet ? complet([info[PHImageResultIsInCloudKey] intValue] && !imageData) : nil;
                });
            }];
        }
    }
}

加載相冊中的照片/視頻

- (void)loadPhotosFromAlbum
{
    __weak AlbumViewController *albumVC = self;
    // 指定要加載的資源類型
    PHAssetMediaType assetType = PHAssetMediaTypeImage;
    if (self.type == MediaTypeVideo) {
        assetType = PHAssetMediaTypeVideo;
    }
    
    // 獲取對應的資源列表
    assetsFetchResult = [PHAsset fetchAssetsWithMediaType:assetType options:nil];
    
    // 遍歷資源對象
    [assetsFetchResult enumerateObjectsUsingBlock:^(PHAsset *obj, NSUInteger idx, BOOL * _Nonnull stop) {
        // 轉換字符串
        NSString *createTimeString = [Utils compareDate:obj.creationDate];
        // 轉換模型
        AlbumPhotoModel *photoModel = [[AlbumPhotoModel alloc] init];
        photoModel.isShowVideoBtn = NO;
        photoModel.createTime = createTimeString;
        photoModel.identifier = obj.localIdentifier;
        photoModel.importTime = [Utils compareDate:[Utils timeZoneToDate:[NSDate date]]];
        photoModel.importDate = [Utils timeZoneToDate:[NSDate date]];
        photoModel.asset = obj;
        photoModel.selected = NO;
        
        // 根據創建時間字符串分類存儲
        NSMutableArray *data = [albumVC.assetDic objectForKey:createTimeString];
        if (data == nil) {      //6AA5251E-A38E-4B96-99B0-DCABD8ACE0D3/L0/001
            data = [NSMutableArray array];
            MediaSectionModel *mediaSectionModel = [[MediaSectionModel alloc] init];
            mediaSectionModel.sectionTimeString = createTimeString;
            mediaSectionModel.currentSectionState = false;
            mediaSectionModel.sectionTime = obj.creationDate;
            [albumVC.timeSections addObject:mediaSectionModel];
            [albumVC.assetDic setObject:data forKey:createTimeString];
        }
        [data addObject:photoModel];
        [albumVC.assets addObject:photoModel];
        
    }];
    //按時間逆序排序
//    self.timeSections = [[[albumVC.timeSections reverseObjectEnumerator] allObjects] mutableCopy];
    self.timeSections = [[Utils sortArray:self.timeSections withKey:@"sectionTime" ascending:false] mutableCopy];
    self.collectionView.sectionTitles = albumVC.timeSections;
    self.collectionView.albumDic = albumVC.assetDic;
    [self.collectionView reloadData];
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM