一、基本配置
開啟共享目錄功能,在 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];
});
}];
}