一、基本配置
開(kāi)啟共享目錄功能午绳,在 Info.plist 文件中添加 UIFileSharingEnabled
這個(gè)Key, 并設(shè)置該值為 YES 即可置侍。在填寫(xiě)完 UIFileSharingEnabled 并回車(chē)后, 發(fā)現(xiàn)會(huì)自動(dòng)更正為Application supports iTunes file sharing , 將值設(shè)置為YES 即可。
開(kāi)啟相冊(cè)權(quán)限,info.plist 文件中添加 NSPhotoLibraryUsageDescription
這個(gè)Key, 并描述開(kāi)啟該功能理由蜡坊。調(diào)用PHPhotoLibrary時(shí)杠输,需要導(dǎo)入 <Photos/Photos.h> 框架。
點(diǎn)擊下載 Demo
二秕衙、檢測(cè)共享目錄中圖片
將圖片文件導(dǎo)入共享目錄中蠢甲。通過(guò) NSFileManager 檢測(cè)該文件夾及文件夾中的圖片是否合法。然后返回有效圖片數(shù)組据忘。例:
// 檢測(cè)圖片鹦牛,有圖片則返回圖片數(shù)組,無(wú)圖則返回nil
+ (NSArray *)checkImportPicture {
// 判斷文件夾
NSFileManager *fileMgr = [NSFileManager defaultManager];
NSString *filePath = [self pictureFilePath];
if (![fileMgr fileExistsAtPath:filePath]) {
NSLog(@"請(qǐng)?jiān)诠蚕砟夸?Documents)中 創(chuàng)建文件夾 ZJHPicture");
return nil;
}
// 判斷文件夾內(nèi)容
NSArray *dirArray = [fileMgr contentsOfDirectoryAtPath:filePath error:nil];
if (!dirArray || !dirArray.count) {
NSLog(@"請(qǐng)?jiān)?ZJHPicture 文件夾內(nèi)添加圖片");
return nil;
}
// 判斷文件是否有效
NSMutableArray *pictureArr = [NSMutableArray arrayWithCapacity:dirArray.count];
for (NSString *path in dirArray) {
NSString *imagePath = [filePath stringByAppendingPathComponent:path];
if ([self validExtentionWithPath:path]) {
// 編碼文件名勇吊,以防含有中文曼追,導(dǎo)致存儲(chǔ)失敗
NSCharacterSet *charSet = [NSCharacterSet URLQueryAllowedCharacterSet];
NSString *encodeStr =
[imagePath stringByAddingPercentEncodingWithAllowedCharacters:charSet];
[pictureArr addObject:encodeStr];
} else {
// 刪除無(wú)效文件,以防占用多余空間
[fileMgr removeItemAtPath:imagePath error:nil];
}
}
if (!pictureArr.count) {
NSLog(@"請(qǐng)?zhí)砑?jpg汉规、png礼殊、jpeg、heic针史、mov 類(lèi)型文件");
return nil;
}
return pictureArr;
}
三晶伦、判斷相冊(cè)權(quán)限
通過(guò)該方法 + (PHAuthorizationStatus)authorizationStatus 獲取相冊(cè)的授權(quán)狀態(tài)。
// 相冊(cè)授權(quán)狀態(tài)
typedef NS_ENUM(NSInteger, PHAuthorizationStatus) {
PHAuthorizationStatusNotDetermined = 0, // 用戶(hù)還沒(méi)有決定是否授權(quán)
PHAuthorizationStatusRestricted, // 訪問(wèn)權(quán)限受限制, 如家長(zhǎng)模式的限制才會(huì)有
PHAuthorizationStatusDenied, // 用戶(hù)拒絕App訪問(wèn)相冊(cè)
PHAuthorizationStatusAuthorized // 用戶(hù)已經(jīng)授權(quán)了訪問(wèn)
} PHOTOS_AVAILABLE_IOS_TVOS(8_0, 10_0);
如果這個(gè)方法返回PHAuthorizationStatusNotDetermined啄枕,則可以使用 + (void)requestAuthorization:(void (^)(PHAuthorizationStatus status))handler 方法提示用戶(hù)授權(quán)對(duì)照片庫(kù)的訪問(wèn)婚陪。例:
// 判斷相冊(cè)權(quán)限
- (void)judgePhotoAuthor {
// 獲取當(dāng)前App的相冊(cè)授權(quán)狀態(tài)
PHAuthorizationStatus authorizationStatus = [PHPhotoLibrary authorizationStatus];
// 判斷授權(quán)狀態(tài)
if (authorizationStatus == PHAuthorizationStatusAuthorized) {
// 如果已經(jīng)授權(quán), 保存圖片
[self saveImage];
}
// 如果沒(méi)決定, 彈出指示框, 讓用戶(hù)選擇
else if (authorizationStatus == PHAuthorizationStatusNotDetermined) {
[PHPhotoLibrary requestAuthorization:^(PHAuthorizationStatus status) {
// 如果用戶(hù)選擇授權(quán), 則保存圖片
if (status == PHAuthorizationStatusAuthorized) {
[self saveImage];
}
}];
} else {
// 前往設(shè)置
NSURL *url = [NSURL URLWithString:UIApplicationOpenSettingsURLString];
[[UIApplication sharedApplication] openURL:url];
}
}
四、獲取相簿
根據(jù)相簿名獲取相簿频祝。通過(guò) PHAssetCollection 類(lèi)獲取相簿集泌参,遍歷搜索集合并取出對(duì)應(yīng)的相簿,然后創(chuàng)建相簿變動(dòng)請(qǐng)求智润,若無(wú)結(jié)果及舍,則通過(guò) PHAssetCollectionChangeRequest 新建相簿變動(dòng)請(qǐng)求。例:
// 創(chuàng)建一個(gè)相簿變動(dòng)請(qǐng)求
- (PHAssetCollectionChangeRequest *)getCurrentPhotoCollection{
// 相簿名
NSString *collName = self.title;
// 獲取相簿集合
PHFetchResult *result =
[PHAssetCollection fetchAssetCollectionsWithType:PHAssetCollectionTypeAlbum
subtype:PHAssetCollectionSubtypeAlbumRegular
options:nil];
// 遍歷選取已創(chuàng)建的相簿
for (PHAssetCollection *assetCollection in result) {
if ([assetCollection.localizedTitle containsString:collName]) {
return [PHAssetCollectionChangeRequest changeRequestForAssetCollection:assetCollection];;
}
}
// 創(chuàng)建新的相簿
return [PHAssetCollectionChangeRequest creationRequestForAssetCollectionWithTitle:collName];
}
五窟绷、存儲(chǔ)圖片锯玛、視頻
+(PHPhotoLibrary *)sharedPhotoLibrary; 獲取共享照片庫(kù)對(duì)象妙色,即獲取 PHPhotoLibrary 的單例蛮寂。
-(void)performChanges:(dispatch_block_t)changeBlock completionHandler:(nullable void(^)(BOOL success, NSError *__nullable error))completionHandler; 異步運(yùn)行changeBlock回調(diào)胸完,來(lái)請(qǐng)求執(zhí)行對(duì)照片庫(kù)的修改缸逃。
Photos會(huì)在任意的串行隊(duì)列上調(diào)用你的changeBlock回調(diào)和handler回調(diào)呈础,如果你的回調(diào)中有需要與UI進(jìn)行交互的內(nèi)容量窘,請(qǐng)將此工作分配到主線程荐捻。
注意點(diǎn)1:創(chuàng)建圖片路徑 url 時(shí)潘明,需要對(duì)含中文的文件名進(jìn)行編碼辐棒,否則病曾,可能導(dǎo)致創(chuàng)建失敗
注意點(diǎn)2:iOS8系統(tǒng)需要在文件路徑添加協(xié)議頭 file://
否則牍蜂,可能導(dǎo)致存儲(chǔ)失敗
注意點(diǎn)3:創(chuàng)建相片請(qǐng)求 PHAssetChangeRequest
時(shí),圖片和視頻要分開(kāi)創(chuàng)建泰涂,圖片使用: creationRequestForAssetFromImageAtFileURL鲫竞;視頻使用:creationRequestForAssetFromVideoAtFileURL。
例:
// 存儲(chǔ)圖片
- (void)saveImage {
// 獲取相片庫(kù)對(duì)象
PHPhotoLibrary *library = [PHPhotoLibrary sharedPhotoLibrary];
// 調(diào)用changeBlock
[library performChanges:^{
// 創(chuàng)建一個(gè)相冊(cè)變動(dòng)請(qǐng)求
PHAssetCollectionChangeRequest *collectionRequest = [self getCurrentPhotoCollection];
// 根據(jù)傳入的相片, 創(chuàng)建相片變動(dòng)請(qǐng)求
NSString *imgStr = self.pictureArr[self.index];
// iOS8系統(tǒng)需要添加 file:// 協(xié)議頭
NSString *fileStr = [NSString stringWithFormat:@"file://%@", imgStr];
NSURL *fileUrl = [NSURL URLWithString:fileStr];
// 視頻逼蒙、圖片類(lèi)型分開(kāi)創(chuàng)建 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];
}
// 創(chuàng)建一個(gè)占位對(duì)象
PHObjectPlaceholder *placeholder = [assetRequest placeholderForCreatedAsset];
// 將占位對(duì)象添加到相冊(cè)請(qǐng)求中
[collectionRequest addAssets:@[placeholder]];
} completionHandler:^(BOOL success, NSError * _Nullable error) {
// 回調(diào)在子線程从绘,需要轉(zhuǎn)到主線程刷新界面
dispatch_async(dispatch_get_main_queue(), ^{
[self saveCompleteWithSuccess:success];
});
}];
}