通過PHPhotoLibrary,將共享目錄中圖片批量導入相冊

一、基本配置

開啟共享目錄功能,在 Info.plist 文件中添加 UIFileSharingEnabled 這個Key, 并設置該值為 YES 即可。在填寫完 UIFileSharingEnabled 并回車后, 發現會自動更正為Application supports iTunes file sharing , 將值設置為YES 即可。

開啟相冊權限,info.plist 文件中添加 NSPhotoLibraryUsageDescription 這個Key, 并描述開啟該功能理由。調用PHPhotoLibrary時,需要導入 <Photos/Photos.h> 框架。

點擊下載 Demo

二、檢測共享目錄中圖片

將圖片文件導入共享目錄中。通過 NSFileManager 檢測該文件夾及文件夾中的圖片是否合法。然后返回有效圖片數組。例:

// 檢測圖片,有圖片則返回圖片數組,無圖則返回nil
+ (NSArray *)checkImportPicture {
    // 判斷文件夾
    NSFileManager *fileMgr = [NSFileManager defaultManager];
    NSString *filePath = [self pictureFilePath];
    if (![fileMgr fileExistsAtPath:filePath]) {
        NSLog(@"請在共享目錄(Documents)中 創建文件夾 ZJHPicture");
        return nil;
    }
    
    // 判斷文件夾內容
    NSArray *dirArray = [fileMgr contentsOfDirectoryAtPath:filePath error:nil];
    if (!dirArray || !dirArray.count) {
        NSLog(@"請在 ZJHPicture 文件夾內添加圖片");
        return nil;
    }
    
    // 判斷文件是否有效
    NSMutableArray *pictureArr = [NSMutableArray arrayWithCapacity:dirArray.count];
    for (NSString *path in dirArray) {
        NSString *imagePath = [filePath stringByAppendingPathComponent:path];
        if ([self validExtentionWithPath:path]) {
            // 編碼文件名,以防含有中文,導致存儲失敗
            NSCharacterSet *charSet = [NSCharacterSet URLQueryAllowedCharacterSet];
            NSString *encodeStr =
            [imagePath stringByAddingPercentEncodingWithAllowedCharacters:charSet];
            [pictureArr addObject:encodeStr];
        } else {
            // 刪除無效文件,以防占用多余空間
            [fileMgr removeItemAtPath:imagePath error:nil];
        }
    }
    if (!pictureArr.count) {
        NSLog(@"請添加 jpg、png、jpeg、heic、mov 類型文件");
        return nil;
    }
    
    return pictureArr;
}

三、判斷相冊權限

通過該方法 + (PHAuthorizationStatus)authorizationStatus 獲取相冊的授權狀態。

// 相冊授權狀態
typedef NS_ENUM(NSInteger, PHAuthorizationStatus) {
    PHAuthorizationStatusNotDetermined = 0, // 用戶還沒有決定是否授權
    PHAuthorizationStatusRestricted,        // 訪問權限受限制, 如家長模式的限制才會有
    PHAuthorizationStatusDenied,            // 用戶拒絕App訪問相冊
    PHAuthorizationStatusAuthorized         // 用戶已經授權了訪問
} PHOTOS_AVAILABLE_IOS_TVOS(8_0, 10_0);

如果這個方法返回PHAuthorizationStatusNotDetermined,則可以使用 + (void)requestAuthorization:(void (^)(PHAuthorizationStatus status))handler 方法提示用戶授權對照片庫的訪問。例:

// 判斷相冊權限
- (void)judgePhotoAuthor {
   
    // 獲取當前App的相冊授權狀態
    PHAuthorizationStatus authorizationStatus = [PHPhotoLibrary authorizationStatus];
    // 判斷授權狀態
    if (authorizationStatus == PHAuthorizationStatusAuthorized) {
        // 如果已經授權, 保存圖片
        [self saveImage];
    }
    // 如果沒決定, 彈出指示框, 讓用戶選擇
    else if (authorizationStatus == PHAuthorizationStatusNotDetermined) {
        [PHPhotoLibrary requestAuthorization:^(PHAuthorizationStatus status) {
            // 如果用戶選擇授權, 則保存圖片
            if (status == PHAuthorizationStatusAuthorized) {
                [self saveImage];
            }
        }];
    } else {
        // 前往設置
        NSURL *url = [NSURL URLWithString:UIApplicationOpenSettingsURLString];
        [[UIApplication sharedApplication] openURL:url];
    }
}

四、獲取相簿

根據相簿名獲取相簿。通過 PHAssetCollection 類獲取相簿集,遍歷搜索集合并取出對應的相簿,然后創建相簿變動請求,若無結果,則通過 PHAssetCollectionChangeRequest 新建相簿變動請求。例:

// 創建一個相簿變動請求
- (PHAssetCollectionChangeRequest *)getCurrentPhotoCollection{
    // 相簿名
    NSString *collName = self.title;
    // 獲取相簿集合
    PHFetchResult *result =
    [PHAssetCollection fetchAssetCollectionsWithType:PHAssetCollectionTypeAlbum
                                             subtype:PHAssetCollectionSubtypeAlbumRegular
                                             options:nil];

    // 遍歷選取已創建的相簿
    for (PHAssetCollection *assetCollection in result) {
        if ([assetCollection.localizedTitle containsString:collName]) {
            return [PHAssetCollectionChangeRequest changeRequestForAssetCollection:assetCollection];;
        }
    }
    
    // 創建新的相簿
    return [PHAssetCollectionChangeRequest creationRequestForAssetCollectionWithTitle:collName];
}

五、存儲圖片、視頻

+(PHPhotoLibrary *)sharedPhotoLibrary; 獲取共享照片庫對象,即獲取 PHPhotoLibrary 的單例。

-(void)performChanges:(dispatch_block_t)changeBlock completionHandler:(nullable void(^)(BOOL success, NSError *__nullable error))completionHandler; 異步運行changeBlock回調,來請求執行對照片庫的修改。
Photos會在任意的串行隊列上調用你的changeBlock回調和handler回調,如果你的回調中有需要與UI進行交互的內容,請將此工作分配到主線程。

注意點1:創建圖片路徑 url 時,需要對含中文的文件名進行編碼,否則,可能導致創建失敗
注意點2:iOS8系統需要在文件路徑添加協議頭 file:// 否則,可能導致存儲失敗
注意點3:創建相片請求 PHAssetChangeRequest 時,圖片和視頻要分開創建,圖片使用: creationRequestForAssetFromImageAtFileURL;視頻使用:creationRequestForAssetFromVideoAtFileURL。
例:

// 存儲圖片
- (void)saveImage {    
    // 獲取相片庫對象
    PHPhotoLibrary *library = [PHPhotoLibrary sharedPhotoLibrary];
    
    // 調用changeBlock
    [library performChanges:^{
        
        // 創建一個相冊變動請求
        PHAssetCollectionChangeRequest *collectionRequest = [self getCurrentPhotoCollection];
        
        // 根據傳入的相片, 創建相片變動請求
        NSString *imgStr = self.pictureArr[self.index];
        // iOS8系統需要添加 file:// 協議頭
        NSString *fileStr = [NSString stringWithFormat:@"file://%@", imgStr];
        NSURL *fileUrl = [NSURL URLWithString:fileStr];
        
        // 視頻、圖片類型分開創建 Request
        NSString *ext = imgStr.pathExtension;
        NSString *extLower = ext.lowercaseString;
        PHAssetChangeRequest *assetRequest = nil;
        if ([extLower isEqualToString:@"mov"]) {
            assetRequest =
            [PHAssetChangeRequest creationRequestForAssetFromVideoAtFileURL:fileUrl];
        } else {
            assetRequest =
            [PHAssetChangeRequest creationRequestForAssetFromImageAtFileURL:fileUrl];
        }
        
        // 創建一個占位對象
        PHObjectPlaceholder *placeholder = [assetRequest placeholderForCreatedAsset];
        // 將占位對象添加到相冊請求中
        [collectionRequest addAssets:@[placeholder]];
        
    } completionHandler:^(BOOL success, NSError * _Nullable error) {
        // 回調在子線程,需要轉到主線程刷新界面
        dispatch_async(dispatch_get_main_queue(), ^{
            [self saveCompleteWithSuccess:success];
        });
    }];
}
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容