iOS 開發(fā)之照片框架PhotoKit

背景:最近項目要做一個類似系統(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

最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

  • 本文轉載自Kayo Lee發(fā)表的文章,本文鏈接:http://kayosite.com/ios-developme...
    JackyHeWei閱讀 10,734評論 10 10
  • 發(fā)現(xiàn) 關注 消息 iOS 第三方庫、插件、知名博客總結 作者大灰狼的小綿羊哥哥關注 2017.06.26 09:4...
    肇東周閱讀 15,426評論 4 61
  • 比起前一段時間的忙碌,最近兩天顯得那么休閑與安逸,前一段也不知道怎么了什么都做不好,什么事都做的那么糟糕,其實忙碌...
    瘋子Selina閱讀 418評論 0 1
  • 離開女兒十多天了,特別想念,晚上一進家門,女兒興沖沖的跑過來,抱著我親了又親,還不停的拍我的肩膀,她在以她的方式在...
    Martin_馬丁閱讀 185評論 0 0
  • ????????????????????
    jiameil閱讀 156評論 0 0

友情鏈接更多精彩內(nèi)容