文档章节

使用Photos框架实现图片多选功能

 业界小白
发布于 2017/01/03 11:19
字数 2048
阅读 184
收藏 0

常用的几个类:

资源类

PHPhotoLibrary 是一个资源库。能够获取相册权限以及对相册的操作
PHFetchResult 是一个结果集。通过方法获取到的相册或者资源组就是被封装成该类返回.
PHAssetCollection 相册,可通过类方法获得想要的相册集合,继承自PHCollection.
PHCollectionList 与PHAssetCollection同级(区别:可以通过地点以及时间分组),用法与PHAssetCollection类似,同样是继承自PHCollection.
PHAsset 是一个独立的资源对象。可以通过类方法对PHCollection对象进行遍历,获得存放Asset对象的结果集,可以直接获得资源的规格数据,若想获得图片以及原图等资源,需要配合PHImageManager对象,继承自PHObject. 
工具类

PHFetchOptions 一个遍历配置类。一般情况下,当存在遍历方法的时候就存在这个类型的参数,里面含有谓词、遍历顺序等属性,可以通过设置这些属性,完成不同的遍历.
PHImageManager 是一个负责渲染资源的类。比如获得PHAsset对象的原图等操作需要使用该类.
PHCachingImageManager 继承自PHImageManager,可以对请求的资源对象进行缓存,这样再次获取时就不需要重新渲染,在加快获取速度的同时也降低了CPU的压力,这里最好对缓存的PHImageRequestID进行一下记录,防止同一资源被无限缓存的尴尬.
PHImageRequestOptions 是一个资源请求的配置类。通常在使用PHImageManager对某个资源进行请求时都会存在此类型的参数,可以在请求资源时对该对象进行设置,获得想要的结果,比如原图.. 

 

PHPhotoLibrary:

相册的监听者,顾名思义,能监听相册的变化,是一个单例。

创建监听者:[[PHPhotoLibrary sharedPhotoLibrary] registerChangeObserver:self];

移除监听者:[[PHPhotoLibrary sharedPhotoLibrary] unregisterChangeObserver:self];

相册变化的回调,即我们的数据更新变化在这个方法中。

PHFetchResult:

相册管理类,通过这个这类我们能获取到系统相册及用户自定义相册。

// 获取系统相册
PHFetchResult *systemAlbums = [PHAssetCollection fetchAssetCollectionsWithType:PHAssetCollectionTypeSmartAlbum subtype:PHAssetCollectionSubtypeAlbumRegular options:nil];  

// 获取用户自定义相册
PHFetchResult *userAlbums = [PHAssetCollection fetchAssetCollectionsWithType:PHAssetCollectionTypeAlbum subtype:PHAssetCollectionSubtypeSmartAlbumUserLibrary options:nil];

PHAssetCollection:

相册对象类,即我们需要对单个相册做处理以获得相册的相关参数,比如相册名、该相册包含的照片数量等。

  /**
     *  获取所有的系统相册
     */
    PHFetchResult * smartAlbum = [PHAssetCollection fetchAssetCollectionsWithType:PHAssetCollectionTypeSmartAlbum subtype:PHAssetCollectionSubtypeAlbumRegular options:nil];
    // 遍历所有的系统相册,对单个相册处理来获取相册的相关属性
    [smartAlbum enumerateObjectsUsingBlock:^(PHAssetCollection * _Nonnull collection, NSUInteger idx, BOOL * _Nonnull stop) {
        if (!([collection.localizedTitle isEqualToString:@"Recently Deleted"] || [collection.localizedTitle isEqualToString:@"Videos"])) {
           PHFetchResult * result = [self fetchAssetsInAssetCollection:collection ascending:NO];
            if (result.count > 0) {
                // 照片模型
                FZJPhotoList * list = [[FZJPhotoList alloc]init];
                // 照片名字
                list.title = [self transformAblumTitle:collection.localizedTitle];
                // 照片数量
                list.photoNum = result.count;
                // 第一张照片
                list.firstAsset = result.firstObject;
                // 所有的照片
                list.assetCollection = collection;
                [photoList addObject:list];
            }
        }
    }];
- (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;
}

PHAsset:

这个类相当于一张照片的实体,但是我们必须通过处理才能变成可见的照片。

//资源媒体的类型
PHAssetMediaType mediaType;

typedef NS_ENUM(NSInteger, PHAssetMediaType) {
    PHAssetMediaTypeUnknown = 0,  //未知类型
    PHAssetMediaTypeImage   = 1,  //图片类型
    PHAssetMediaTypeVideo   = 2,  //视频类型
    PHAssetMediaTypeAudio   = 3,  //音频类型
} NS_ENUM_AVAILABLE_IOS(8_0);

//资源美图的子类型,比如如果资源是图片,那么它是全景还是HDR,如果是iOS9,还能知道他是屏幕截图还是live图片,枚举有点多,也不再次粘贴了.
PHAssetMediaSubtype mediaSubtypes;

//资源的像素宽
NSUInteger pixelWidth;

//资源的像素高
NSUInteger pixelHeight;

//资源的创建日期
NSDate *creationDate;

//资源的最近一次修改的时间
NSDate *modificationDate;

//资源拍摄的地点
CLLocation *location;

//如果是音频或者视频,它的持续时间
NSTimeInterval duration;

//它是否被隐藏
BOOL hidden;

//它是否是喜爱的
BOOL favorite;

// 常用的方法
//请求图片,将想要获取Image实体的资源,裁剪的大小以及方式进行获取图片
//如果想要原图,设置PHImageRequestOptions对象的deliveryMode属性为PHImageRequestOptionsDeliveryModeHighQualityFormat即可
[[PHImageManager defaultManager]requestImageForAsset:(PHAsset *)asset
                                          targetSize:(CGSize)targetSize
                                         contentMode:(PHImageContentMode)contentMode
                                             options:(nullable PHImageRequestOptions *)options
                                       resultHandler:^(UIImage * _Nullable result, NSDictionary * _Nullable info) {

    //通过block回传图片,并将部分信息存在于info字典中,并且该方法的返回值可以在info字典中找到
}];

//请求数据,获取资源的Data对象,可以用来计算资源的大小。
//这样可以避免UIImage->Data导致内存以及CPU瞬间激增
[[PHImageManager defaultManager]requestImageDataForAsset:(PHAsset *)asset
                                                 options:(nullable PHImageRequestOptions *)options
                                           resultHandler:^(NSData * _Nullable imageData, NSString * _Nullable dataUTI, UIImageOrientation orientation, NSDictionary * _Nullable info) {
    //在block里面获取图片的各种信息
}];

实例:


#import <Foundation/Foundation.h>
#import <Photos/Photos.h>

@interface FZJPhotoList : NSObject
/**
 *  相册的名字
 */
@property(nonatomic,strong)NSString * title;
/**
 *  该相册的照片数量
 */
@property(nonatomic,assign)NSInteger  photoNum;
/**
 *  该相册的第一张图片
 */
@property(nonatomic,strong)PHAsset * firstAsset;
/**
 *  同过该属性可以取得该相册的所有照片
 */
@property(nonatomic,strong)PHAssetCollection * assetCollection;

@end


@interface FZJPhotoTool : NSObject

+(instancetype)defaultFZJPhotoTool;
/**
 *  获得所有的相册
 *
 *  @return  FZJPhotoList样式的相册
 */

-(NSArray<FZJPhotoList *> *)getAllPhotoList;

/**
 *  取到对应的照片实体
 *
 *  @param asset      索取照片实体的媒介
 *  @param size       实际想要的照片大小
 *  @param resizeMode 控制照片尺寸
 *  @param completion block返回照片实体
 */
-(void)getImageByAsset:(PHAsset *)asset makeSize:(CGSize)size makeResizeMode:(PHImageRequestOptionsResizeMode)resizeMode completion:(void (^)(UIImage * AssetImage))completion;

/**
 *   取得所有的照片资源
 *
 *  @param ascending 排序方式
 *
 *  @return 照片资源
 */

-(NSArray<PHAsset *> *)getAllAssetInPhotoAblumWithAscending:(BOOL)ascending;

/**
 *  获取指定相册内的所有图片
 */
- (NSArray<PHAsset *> *)getAssetsInAssetCollection:(PHAssetCollection *)assetCollection ascending:(BOOL)ascending;


@end
#import "FZJPhotoTool.h"

@implementation FZJPhotoList

@end

@implementation FZJPhotoTool
+(instancetype)defaultFZJPhotoTool{
    
    static FZJPhotoTool * manager = nil;
    
    @synchronized(manager) {
        if (manager == nil) {
            manager = [[self alloc]init];
        }
    }
    return manager;
    
}

- (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:@"My Photo Stream"]){
        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;
}

-(NSArray<FZJPhotoList *> *)getAllPhotoList{
    
    NSMutableArray<FZJPhotoList *> * photoList = [NSMutableArray array];
    /**
     *  获取所有的系统相册
     */
    PHFetchResult * smartAlbum = [PHAssetCollection fetchAssetCollectionsWithType:PHAssetCollectionTypeSmartAlbum subtype:PHAssetCollectionSubtypeAlbumRegular options:nil];
    // 遍历所有的系统相册,对单个相册处理来获取相册的相关属性
    [smartAlbum enumerateObjectsUsingBlock:^(PHAssetCollection * _Nonnull collection, NSUInteger idx, BOOL * _Nonnull stop) {
        if (!([collection.localizedTitle isEqualToString:@"Recently Deleted"] || [collection.localizedTitle isEqualToString:@"Videos"])) {
           PHFetchResult * result = [self fetchAssetsInAssetCollection:collection ascending:NO];
            if (result.count > 0) {
                // 照片模型
                FZJPhotoList * list = [[FZJPhotoList alloc]init];
                // 照片名字
                list.title = [self transformAblumTitle:collection.localizedTitle];
                // 照片数量
                list.photoNum = result.count;
                // 第一张照片
                list.firstAsset = result.firstObject;
                // 所有的照片
                list.assetCollection = collection;
                [photoList addObject:list];
            }
        }
    }];
    /**
     *  用户创建的相册
     */
    PHFetchResult * userAlbum = [PHAssetCollection fetchAssetCollectionsWithType:PHAssetCollectionTypeAlbum subtype:PHAssetCollectionSubtypeSmartAlbumUserLibrary options:nil];
    [userAlbum enumerateObjectsUsingBlock:^(PHAssetCollection * _Nonnull collection, NSUInteger idx, BOOL * _Nonnull stop) {
        PHFetchResult *result = [self fetchAssetsInAssetCollection:collection ascending:NO];
        if (result.count > 0) {
            FZJPhotoList * list = [[FZJPhotoList alloc]init];
            list.title = [self transformAblumTitle:collection.localizedTitle];
            if (list.title == nil) {
                list.title = collection.localizedTitle;
            }
            list.photoNum = result.count;
            list.firstAsset = result.firstObject;
            list.assetCollection = collection;
            [photoList addObject:list];

        }
    }];
    
    
    return photoList;
}

#pragma mark ---   获取asset相对应的照片
-(void)getImageByAsset:(PHAsset *)asset makeSize:(CGSize)size makeResizeMode:(PHImageRequestOptionsResizeMode)resizeMode completion:(void (^)(UIImage *))completion{
    
    PHImageRequestOptions *option = [[PHImageRequestOptions alloc] init];
    /**
     resizeMode:对请求的图像怎样缩放。有三种选择:None,不缩放;Fast,尽快地提供接近或稍微大于要求的尺寸;Exact,精准提供要求的尺寸。
     deliveryMode:图像质量。有三种值:Opportunistic,在速度与质量中均衡;HighQualityFormat,不管花费多长时间,提供高质量图像;FastFormat,以最快速度提供好的质量。
     这个属性只有在 synchronous 为 true 时有效。
     */
    option.resizeMode = resizeMode;//控制照片尺寸
    option.deliveryMode = PHImageRequestOptionsDeliveryModeHighQualityFormat;//控制照片质量
    // 是否阻塞知道获取图片
    option.synchronous = YES;
    // 是否同步iCloud
    option.networkAccessAllowed = NO;
    //param:targetSize 即你想要的图片尺寸,若想要原尺寸则可输入PHImageManagerMaximumSize
    [[PHCachingImageManager defaultManager] requestImageForAsset:asset targetSize:size contentMode:PHImageContentModeAspectFit options:option resultHandler:^(UIImage * _Nullable image, NSDictionary * _Nullable info) {
        completion(image);
    }];

}

#pragma mark ----  取到所有的asset资源
- (NSArray<PHAsset *> *)getAllAssetInPhotoAblumWithAscending:(BOOL)ascending{
    NSMutableArray<PHAsset *> *assets = [NSMutableArray array];
    
    PHFetchOptions *option = [[PHFetchOptions alloc] init];
    //ascending 为YES时,按照照片的创建时间升序排列;为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 ---  获得指定相册的所有照片
- (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) {
        [arr addObject:obj];
    }];
    return arr;
}
@end

 

 

 

 

 

© 著作权归作者所有

共有 人打赏支持
粉丝 1
博文 55
码字总数 62553
作品 0
洛阳
iOS工程师
私信 提问
iOS下将照片保存到相册的三种方法

方法一 使用UIImageWriteToSavedPhotosAlbum函数将图片保存到相册,如: 第一个参数是要保存到相册的图片对象 第二个参数是保存完成后回调的目标对象 第三个参数就是保存完成后回调到目标对象...

vimfung
2016/06/30
1K
0
Android实用视图动画及工具系列之九:漂亮的图片选择器,高性能防崩溃图片选择工具

实现效果 -------------------------------------------------------------------------------------------------------------------- 请在Github下查阅用法(最新更新和用法都在github上第一......

jaikydota163
2016/08/02
0
0
三步为你的App集成LivePhoto功能

摘要:LivePhoto是iOS9新推出的一种拍照方式,类似于拍摄Gif图或录制视频片段生成图片。如果没有画面感,可以联想《哈利波特》霍格沃茨城堡的壁画,哈哈,很炫酷有木有,但坑爹的是只有iphone6S以...

壹峰
2018/06/20
0
0
如果让我重新设计一款Android App

开发工具的选择 开发工具我将选用Android Studio,它是Google官方指定的Android开发工具,目前是1.2.2稳定版,1.3的预览版也已经发布了。Android Studio的优点就不需多说了,GitHub上大部分的...

AlexMahoneFBI
2015/11/13
0
1
ios9下照片浏览模糊的解决方法(ALAsset.thumbnail模糊)

在ios9下,使用ALAsset方式实现的照片浏览器都存在照片模糊的问题,但是目前能找到的大部分开源的照片浏览器都是使用这个框架编写的。 我们通常用以下方法获得照片缩略图: self.image = [UI...

cuibo1123
2015/10/12
0
0

没有更多内容

加载失败,请刷新页面

加载更多

为什么强烈建议大家使用枚举来实现单例

关于单例模式,我的博客中有很多文章介绍过。作为23种设计模式中最为常用的设计模式,单例模式并没有想象的那么简单。因为在设计单例的时候要考虑很多问题,比如线程安全问题、序列化对单例的...

群星纪元
25分钟前
8
0
Confluence 6 超过当前许可证期限进行升级

这个页面将会对你在进行 Confluence 升级的时候超过了当前许可证的期限进行升级的情况。 许可证警告 在升级的过程中,你将会在 Confluence 的应用程序日志(log file)中看到类似下面的错误提...

honeymoose
38分钟前
2
0
顶尖战略咨询公司常用分析模型

1、KANO模型 日本教授狩野纪昭(Noriaki Kano)构建出的kano模型。将影响用户满意度的因素划分为五个类型,包括: 魅力因素:用户意想不到的,如果不提供此需求,用户满意度不会降低,但当提供...

Moks角木
54分钟前
2
0
Linux iptables之mangle表使用案例

mangle表的用途 mangle表的主要功能是根据规则修改数据包的一些标志位,以便其他规则或程序可以利用这种标志对数据包进行过滤或策略路由。 mangel表使用示例 示例1-策略路由1 内网的客户机通...

月下狼
今天
3
0
OSChina 周日乱弹 —— 兼职我想去学学布偶戏

Osc乱弹歌单(2019)请戳(这里) 【今日歌曲】 @clouddyy : 《火炎 - 女王蜂》 《火炎 - 女王蜂》 手机党少年们想听歌,请使劲儿戳(这里) @小鱼丁 :还在睡觉突然接到一个小哥哥电话“x...

小小编辑
今天
223
8

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部