背景:最近項目要做一個類似系統(tǒng)相冊的功能,例如咱們的app拍的照片保存在了自定義的相冊中,然后去用我寫的這個相冊去展示它。本文主要是如何使用PhotoKit框架訪問系統(tǒng)的相冊、照片,因為這個框架是iOS8出來的,所以不支持iOS7??。
下面看我封裝的這個訪問系統(tǒng)相冊的框架
//
// YBSystemPhotoTool.h
// sway
//
// Created by wyb on 2017/2/16.
// Copyright ? 2017年 xxx. All rights reserved.
//
//此工具支持iOS8.0及以上
#import <Foundation/Foundation.h>
#import <Photos/Photos.h>
//相冊的model
@interface YBPhotoAblumModel : NSObject
@property (nonatomic, copy) NSString *title; //相冊名字
@property (nonatomic, assign) NSInteger count; //該相冊內(nèi)相片數(shù)量
@property (nonatomic, strong) PHAsset *headImageAsset; //相冊第一張圖片縮略圖
@property (nonatomic, strong) PHAssetCollection *assetCollection; //相冊集,通過該屬性獲取該相冊集下所有照片
@end
/*---------------------------------------分割線-------------------------------------------*/
@interface YBSystemPhotoTool : NSObject
+ (instancetype)sharePhotoTool;
/**
* @brief 獲取用戶所有相冊列表
*/
- (NSArray<YBPhotoAblumModel *> *)getPhotoAblumList;
/**
* @brief 獲取相冊內(nèi)所有圖片資源
* @param ascending 是否按創(chuàng)建時間正序排列 YES,創(chuàng)建時間正(升)序排列; NO,創(chuàng)建時間倒(降)序排列
*/
- (NSArray<PHAsset *> *)getAllAssetInPhotoAblumWithAscending:(BOOL)ascending;
/**
* @brief 獲取指定相冊內(nèi)的所有圖片
*/
- (NSArray<PHAsset *> *)getAssetsInAssetCollection:(PHAssetCollection *)assetCollection ascending:(BOOL)ascending;
/**
* @brief 獲取每個Asset對應的圖片
*/
- (void)requestImageForAsset:(PHAsset *)asset size:(CGSize)size resizeMode:(PHImageRequestOptionsResizeMode)resizeMode completion:(void (^)(UIImage *image))completion;
/**
刪除系統(tǒng)相冊中的照片,單個或者多個
@param assets 要刪除的照片數(shù)組
@param completionHandler 成功的回調(diào)
*/
- (void)deleteSystemPhothWithPhotos:(NSArray<PHAsset *>*)assets successHandler:(dispatch_block_t)completionHandler;
#pragma mark - 判斷軟件是否有相冊訪問權限
+ (BOOL)judgeIsHavePhotoAblumAuthority;
#pragma mark - 判斷軟件是否有相機訪問權限
+ (BOOL)judgeIsHaveCameraAuthority;
@end
//
// YBSystemPhotoTool.m
// sway
//
// Created by wyb on 2017/2/16.
// Copyright ? 2017年 xxx. All rights reserved.
//
#import "YBSystemPhotoTool.h"
@implementation YBPhotoAblumModel
@end
/*---------------------------------------分割線-------------------------------------------*/
@implementation YBSystemPhotoTool
static YBSystemPhotoTool *sharePhotoTool = nil;
+ (instancetype)sharePhotoTool
{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharePhotoTool = [[self alloc] init];
});
return sharePhotoTool;
}
+ (instancetype)allocWithZone:(struct _NSZone *)zone
{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharePhotoTool = [super allocWithZone:zone];
});
return sharePhotoTool;
}
#pragma mark - 獲取所有相冊列表
- (NSArray<YBPhotoAblumModel *> *)getPhotoAblumList
{
NSMutableArray<YBPhotoAblumModel *> *photoAblumList = [NSMutableArray array];
//獲取所有智能相冊
PHFetchResult *smartAlbums = [PHAssetCollection fetchAssetCollectionsWithType:PHAssetCollectionTypeSmartAlbum subtype:PHAssetCollectionSubtypeAlbumRegular options:nil];
[smartAlbums enumerateObjectsUsingBlock:^(PHAssetCollection * _Nonnull collection, NSUInteger idx, BOOL *stop) {
//過濾掉視頻和最近刪除
if (!([collection.localizedTitle isEqualToString:@"Recently Deleted"] ||
[collection.localizedTitle isEqualToString:@"Videos"])) {
NSArray<PHAsset *> *assets = [self getAssetsInAssetCollection:collection ascending:NO];
if (assets.count > 0) {
YBPhotoAblumModel *ablum = [[YBPhotoAblumModel alloc] init];
ablum.title = [self transformAblumTitle:collection.localizedTitle];
ablum.count = assets.count;
ablum.headImageAsset = assets.firstObject;
ablum.assetCollection = collection;
[photoAblumList addObject:ablum];
}
}
}];
//獲取用戶創(chuàng)建的相冊
PHFetchResult *userAlbums = [PHAssetCollection fetchAssetCollectionsWithType:PHAssetCollectionTypeAlbum subtype:PHAssetCollectionSubtypeSmartAlbumUserLibrary options:nil];
[userAlbums enumerateObjectsUsingBlock:^(PHAssetCollection * _Nonnull collection, NSUInteger idx, BOOL * _Nonnull stop) {
NSArray<PHAsset *> *assets = [self getAssetsInAssetCollection:collection ascending:NO];
if (assets.count > 0) {
YBPhotoAblumModel *ablum = [[YBPhotoAblumModel alloc] init];
ablum.title = collection.localizedTitle;
ablum.count = assets.count;
ablum.headImageAsset = assets.firstObject;
ablum.assetCollection = collection;
[photoAblumList addObject:ablum];
}
}];
return photoAblumList;
}
- (NSString *)transformAblumTitle:(NSString *)title
{
if ([title isEqualToString:@"Slo-mo"]) {
return @"慢動作";
} else if ([title isEqualToString:@"Recently Added"]) {
return @"最近添加";
} else if ([title isEqualToString:@"Favorites"]) {
return @"最愛";
} else if ([title isEqualToString:@"Recently Deleted"]) {
return @"最近刪除";
} else if ([title isEqualToString:@"Videos"]) {
return @"視頻";
} else if ([title isEqualToString:@"All Photos"]) {
return @"所有照片";
} else if ([title isEqualToString:@"Selfies"]) {
return @"自拍";
} else if ([title isEqualToString:@"Screenshots"]) {
return @"屏幕快照";
} else if ([title isEqualToString:@"Camera Roll"]) {
return @"相機膠卷";
} else if ([title isEqualToString:@"Panoramas"]) {
return @"全景照片";
}
return nil;
}
- (PHFetchResult *)fetchAssetsInAssetCollection:(PHAssetCollection *)assetCollection ascending:(BOOL)ascending
{
PHFetchOptions *option = [[PHFetchOptions alloc] init];
option.sortDescriptors = @[[NSSortDescriptor sortDescriptorWithKey:@"creationDate" ascending:ascending]];
PHFetchResult *result = [PHAsset fetchAssetsInAssetCollection:assetCollection options:option];
return result;
}
#pragma mark - 獲取相冊內(nèi)所有照片資源
- (NSArray<PHAsset *> *)getAllAssetInPhotoAblumWithAscending:(BOOL)ascending
{
NSMutableArray<PHAsset *> *assets = [NSMutableArray array];
PHFetchOptions *option = [[PHFetchOptions alloc] init];
//ascending 為YES時,按照照片的創(chuàng)建時間升序排列;為NO時,則降序排列
option.sortDescriptors = @[[NSSortDescriptor sortDescriptorWithKey:@"creationDate" ascending:ascending]];
PHFetchResult *result = [PHAsset fetchAssetsWithMediaType:PHAssetMediaTypeImage options:option];
[result enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
PHAsset *asset = (PHAsset *)obj;
[assets addObject:asset];
}];
return assets;
}
#pragma mark - 獲取指定相冊內(nèi)的所有圖片
- (NSArray<PHAsset *> *)getAssetsInAssetCollection:(PHAssetCollection *)assetCollection ascending:(BOOL)ascending
{
NSMutableArray<PHAsset *> *arr = [NSMutableArray array];
PHFetchResult *result = [self fetchAssetsInAssetCollection:assetCollection ascending:ascending];
[result enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
if (((PHAsset *)obj).mediaType == PHAssetMediaTypeImage) {
[arr addObject:obj];
}
}];
return arr;
}
#pragma mark - 獲取asset對應的圖片
- (void)requestImageForAsset:(PHAsset *)asset size:(CGSize)size resizeMode:(PHImageRequestOptionsResizeMode)resizeMode completion:(void (^)(UIImage *))completion
{
PHImageRequestOptions *option = [[PHImageRequestOptions alloc] init];
/**
resizeMode:對請求的圖像怎樣縮放。有三種選擇:None,默認加載方式;Fast,盡快地提供接近或稍微大于要求的尺寸;Exact,精準提供要求的尺寸。
deliveryMode:圖像質(zhì)量。有三種值:Opportunistic,在速度與質(zhì)量中均衡;HighQualityFormat,不管花費多長時間,提供高質(zhì)量圖像;FastFormat,以最快速度提供好的質(zhì)量。
這個屬性只有在 synchronous 為 true 時有效。
*/
option.resizeMode = resizeMode;//控制照片尺寸
//option.deliveryMode = PHImageRequestOptionsDeliveryModeOpportunistic;//控制照片質(zhì)量
//option.synchronous = YES;
option.networkAccessAllowed = YES;
//param:targetSize 即你想要的圖片尺寸,若想要原尺寸則可輸入PHImageManagerMaximumSize
[[PHCachingImageManager defaultManager] requestImageForAsset:asset targetSize:size contentMode:PHImageContentModeAspectFit options:option resultHandler:^(UIImage * _Nullable image, NSDictionary * _Nullable info) {
completion(image);
}];
}
- (void)deleteSystemPhoth:(dispatch_block_t)changeBlock completionHandler:(nullable void(^)(BOOL success, NSError *__nullable error))completionHandler{
[[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{
changeBlock();
} completionHandler:^(BOOL success, NSError * _Nullable error) {
completionHandler(success,error);
}];
}
- (void)deleteSystemPhothWithPhotos:(NSArray<PHAsset *>*)assets successHandler:(dispatch_block_t)completionHandler{
[[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{
[PHAssetChangeRequest deleteAssets:assets];
} completionHandler:^(BOOL success, NSError *error) {
if (success == YES) {
completionHandler();
}
}];
}
#pragma mark - 判斷軟件是否有相冊訪問權限
+ (BOOL)judgeIsHavePhotoAblumAuthority
{
PHAuthorizationStatus status = [PHPhotoLibrary authorizationStatus];
if (status == PHAuthorizationStatusRestricted ||
status == PHAuthorizationStatusDenied) {
return NO;
}
return YES;
}
#pragma mark - 判斷軟件是否有相機訪問權限
+ (BOOL)judgeIsHaveCameraAuthority
{
AVAuthorizationStatus status = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo];
if (status == AVAuthorizationStatusRestricted ||
status == AVAuthorizationStatusDenied) {
return NO;
}
return YES;
}
@end
-
系統(tǒng)的相冊
084573F1-7140-4033-8A18-D3DF1E75CB1D.png
-
點擊查看大圖
QQ20170226-173918@2x.png demo地址在這里哦
自定義相冊的使用
#import "ViewController.h"
#import <Photos/Photos.h>
/** 相冊名字 */
static NSString * const CollectionName = @"wyb-photo";
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
[self searchAllImages];
}
#pragma mark - 查詢相冊中的圖片
/**
* 查詢所有的圖片
*/
- (IBAction)searchAllImages {
// 判斷授權狀態(tài)
[PHPhotoLibrary requestAuthorization:^(PHAuthorizationStatus status) {
if (status != PHAuthorizationStatusAuthorized) return;
dispatch_async(dispatch_get_main_queue(), ^{
// 遍歷所有的自定義相冊
PHFetchResult<PHAssetCollection *> *collectionResult0 = [PHAssetCollection fetchAssetCollectionsWithType:PHAssetCollectionTypeAlbum subtype:PHAssetCollectionSubtypeAlbumRegular options:nil];
for (PHAssetCollection *collection in collectionResult0) {
[self searchAllImagesInCollection:collection];
}
// 獲得相機膠卷的圖片
PHFetchResult<PHAssetCollection *> *collectionResult1 = [PHAssetCollection fetchAssetCollectionsWithType:PHAssetCollectionTypeSmartAlbum subtype:PHAssetCollectionSubtypeAlbumRegular options:nil];
for (PHAssetCollection *collection in collectionResult1) {
if (![collection.localizedTitle isEqualToString:@"Camera Roll"]) continue;
[self searchAllImagesInCollection:collection];
break;
}
});
}];
}
/**
* 查詢某個相冊里面的所有圖片
*/
- (void)searchAllImagesInCollection:(PHAssetCollection *)collection
{
// 采取同步獲取圖片(只獲得一次圖片)
PHImageRequestOptions *imageOptions = [[PHImageRequestOptions alloc] init];
imageOptions.synchronous = YES;
NSLog(@"相冊名字:%@", collection.localizedTitle);
// 遍歷這個相冊中的所有圖片
PHFetchResult<PHAsset *> *assetResult = [PHAsset fetchAssetsInAssetCollection:collection options:nil];
for (PHAsset *asset in assetResult) {
// 過濾非圖片
if (asset.mediaType != PHAssetMediaTypeImage) continue;
// 圖片原尺寸
CGSize targetSize = CGSizeMake(asset.pixelWidth, asset.pixelHeight);
// 請求圖片
[[PHImageManager defaultManager] requestImageForAsset:asset targetSize:targetSize contentMode:PHImageContentModeDefault options:imageOptions resultHandler:^(UIImage * _Nullable result, NSDictionary * _Nullable info) {
NSLog(@"圖片:%@ %@", result, [NSThread currentThread]);
}];
}
}
#pragma mark - 保存圖片到自定義相冊
/**
* 獲得自定義的相冊對象
*/
- (PHAssetCollection *)collection
{
// 先從已存在相冊中找到自定義相冊對象
PHFetchResult<PHAssetCollection *> *collectionResult = [PHAssetCollection fetchAssetCollectionsWithType:PHAssetCollectionTypeAlbum subtype:PHAssetCollectionSubtypeAlbumRegular options:nil];
for (PHAssetCollection *collection in collectionResult) {
if ([collection.localizedTitle isEqualToString:CollectionName]) {
return collection;
}
}
// 新建自定義相冊
__block NSString *collectionId = nil;
NSError *error = nil;
[[PHPhotoLibrary sharedPhotoLibrary] performChangesAndWait:^{
collectionId = [PHAssetCollectionChangeRequest creationRequestForAssetCollectionWithTitle:CollectionName].placeholderForCreatedAssetCollection.localIdentifier;
} error:&error];
if (error) {
NSLog(@"獲取相冊【%@】失敗", CollectionName);
return nil;
}
return [PHAssetCollection fetchAssetCollectionsWithLocalIdentifiers:@[collectionId] options:nil].lastObject;
}
/**
* 保存圖片到相冊
*/
- (IBAction)saveImage {
// 判斷授權狀態(tài)
[PHPhotoLibrary requestAuthorization:^(PHAuthorizationStatus status) {
if (status != PHAuthorizationStatusAuthorized) return;
dispatch_async(dispatch_get_main_queue(), ^{
NSError *error = nil;
// 保存相片到相機膠卷
__block PHObjectPlaceholder *createdAsset = nil;
[[PHPhotoLibrary sharedPhotoLibrary] performChangesAndWait:^{
createdAsset = [PHAssetCreationRequest creationRequestForAssetFromImage:[UIImage imageNamed:@"logo"]].placeholderForCreatedAsset;
} error:&error];
if (error) {
NSLog(@"保存失敗:%@", error);
return;
}
// 拿到自定義的相冊對象
PHAssetCollection *collection = [self collection];
if (collection == nil) return;
[[PHPhotoLibrary sharedPhotoLibrary] performChangesAndWait:^{
[[PHAssetCollectionChangeRequest changeRequestForAssetCollection:collection] insertAssets:@[createdAsset] atIndexes:[NSIndexSet indexSetWithIndex:0]];
} error:&error];
if (error) {
NSLog(@"保存失?。?@", error);
} else {
NSLog(@"保存成功");
}
});
}];
}
@end

