iOS中获取系统相册中的图片

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了iOS中获取系统相册中的图片相关的知识,希望对你有一定的参考价值。

参考技术A

1、利用UIImagePickerController可以从系统自带的App中获得图片
2、设置代理,遵守代理协议

3、实现代理方法didFinishPickingMediaWithInfo

思路:
1、导入头文件#import <Photos/Photos.h>
2、PHAsset:一个资源,比如一张图片或者一段视频
3、PHAssetCollection:一个相簿
4、PHImageManager 图片管理者,是单例,发送请求才能从asset获取图片
5、PHImageRequestOptions图片请求选项
6、注意:这个类是ios8开始推广,iOS9开始废弃之前的方法
系统适配iOS8之前,用下面的这个库里面的API

照片库中有两种资源可供获取:PHAsset和PHCollection,前者代表图像或视频对象,后者是前者的集合或者自身类型的集合。PHCollection是一个基类,有PHAssetCollection和PHCollectionList两个子类,分别代表Photos里面的相册和文件夹。PHCollectionList里面可嵌套PHAssetCollection和自身类型,还支持多重嵌套。获取PHAsset以及PHAssetCollection的过程类似于CoreData,如下所示,只能通过类方法来返回PHFetchResult,遍历返回结果来获取需要的资源。

注意,PHAsset、PHAssetCollection和PHCollectionList都是轻量级的不可变对象,使用这些类时并没有将其代表的图像或视频或者集合载入内存中,要使用其代表的图像或视频,需要通过PHImageManager类来请求。

关于PHImageManager类,

你不应该生成该类的实例,而是应该使用该类的提供的单例对象,该方法提供指定的尺寸的图像,与ALAssetLibrary库相比,没有了方便的缩略图提供,但是ALAssetLibrary库提供的缩略图往往尺寸太小而且质量很低,用在TableView上还行。
该方法在默认情况下是异步执行的,而且Photos库可能会很多次执行resultHandler块,因为对于制定的尺寸,Photos可能会提供底质量的图像已供临时显示,随后会将指定尺寸的图像返回,如果指定尺寸的高质量的图像有缓存,那么直接提供高质量的图像,而这些行为,可以通过options参数来定制。

PHImageRequestOptions类用于定制请求,上面的方法返回指定尺寸的图像,如果你仅仅指定必要的参数而没有对options进行配置的话,返回的图像尺寸将会是原始图像的尺寸,或者你指定的尺寸很小,这时候会按照你的要求来返回接近改尺寸的图像。
PHImageRequestOptions有以下几个重要的属性:

resizeMode默认是None,这也造成了返回图像尺寸与要求尺寸不符,这点需要注意。这个要返回一个指定尺寸的图像要避免两层陷阱:一定要指定options参数,resizeMode不能为None。

除了必要的请求图像或是视频的功能外,PHImageManager添加了两大功能:
1、缓存图像,由于其之类PHCachingImageManager实现,缓存效率和空间管理能满足大部分场景的需求;
2、裁剪图像,这个功能很久以前就有强烈的需求。

Photos框架推出时,和原来的照片库AssetLibrary框架之间还有些交互,PHAsset类的+ fetchAssetWithALAssetURLs:options: 和PHAssetCollection类的+ fetchAssetCollectionsWithALAssetGroupURLs:options:可以利用原来的AssetsLibrary提供的URL进行转化,而在iOS9 中,原来的照片框架AssertLibrary已经被废弃了,官方要淡化照片库中URL的概念,改之使用一个标识符唯一代表一个资源,Photos框架中的根类PHObject只有一个公开接口localIdentifier,AssetsLibrary框架中无论是Asset还是AssetGroup的URL也是唯一标识符,而且同时还是动态变化的,每次启动应用后获取的URL和上一次是不一样的,而且AssetGroup有一个PersistentID与PHObject的localidentifier 类似,但获取比较麻烦。
localIdentifier属性带来的最大好处就是PHObject类实现了NSCopying协议,可以直接使用localIdentifier属性对PHObject以及子类对象进行对比是否同一个对象。

通过PHAssetCollection的以下方法来获取指定的相册:

这个方法需要至少指定两个参数:

注意,获取指定类型的相册时,主类型和子类型要匹配,如果不匹配,系统会按照Any子类型来处理,对于Moment类型,子类型使用Any.
1.获取用户自己建立的相册和文件夹我称之为逻辑相册,非系统相册和从 iTunes 同步来的相册)有两种方法:

在没有提供PHOptions的情况下,返回的PHFetchResult结果是按相册的建立时间排序的,最新的在前面
2.获取相机相册:

另外 :PHAsset
的获取方式在 iOS 8.1 后发生了一些变化。以下的两个方法在 iOS 8.1后不再包含从 iTunes 同步以及在 iCloud 中的照片和视频。要获取 iOS 设备上本地的所有照片和资源只能从 PHAssetCollection 入手了。

对照片库进行操作,可参见官方文档 Requesting Changes to the Photo Library ,照片库中的资源都有对应的变更请求类: PHAssetChangeRequest , PHAssetCollectionChangeRequest 和 PHCollectionListChangeRequest ,而这些操作的请求都要求在 phphotoLibrary 的performChanges(_ changeBlock: dispatch_block_t!, completionHandler completionHandler: ((Bool, NSError!) -> Void)!)中的changeBlock中执行。注意这里只是发出请求并没有做出实质的更改,因此想要根据更改结果更新UI的话不要在completionHandler中进行,而应该在photoLibraryDidChange(changeInfo:PHChange!)中进行。三种变更请求中,删除和编辑操作都比较简单,而添加操作有需要注意的地方。

在相册中添加照片:

在文件夹中添加相册:

在文件夹中添加子文件夹:

对相册发出变更请求后,系统会通知用户是否允许,用户允许后才会发生实质上的变化,系统会发布通知。
首先,注册成为PHPhotoLibrary的观察者来接收变化通知:

然后,实现PHPhotoLibraryChangeObserver协议的photoLibraryDidChange(changeInfo:PHChange!)。官方一个很好的例子: Handing Changes:An Example ,有以下几点需要注意:

获取所有用户建立的相册和文件夹,在photoLibraryDidChange(changeInfo:PHChange!)中通过以下方法获得PHFetchResultChangeDetails对象。

fetchChangeDetails.changeObject返回一组其内容或元数据发生变化的成员,返回的成员是跟新后的成员对象。当用户对某个文件夹内的相册或子文件夹进行添加、删除和编辑操作即文件夹的内容而不是文件夹本身的属性发生变化时,通知中会该变化的信息,实际上只有在文件夹中添加相册或子文件夹时才会在fetchChangeDetails.changedObject中有所反应,而删除成员或是修改元数据等操作都不会再通知中有所反应,你需要使用其他手段来跟踪变化

iOS开发之获取系统相册ALAssetLibrary

ALAssetsLibrary包含,ALAssetsLibrary,ALAssetsGroup,ALAsset,ALAssetsFilter,ALAssetRepresentation几个类

1、框架解析

 

(1) ALAssetsLibrary

 ALAssetsLibrary类可以实现查看相册列表,增加相册,保存图片到相册等功能

 具体实现见框架使用

 

(2) ALAssetsGroup

 ALAssetsGroup就是相册的类,可以通过ALAssetsLibrary遍历得到相册ALAssetsGroup

 

通过valueForProperty:获取相册名称

[assetsGroup valueForProperty:ALAssetsGroupPropertyName]

 

 ALAssetsGroup 可以使用setAssetsFilter:(ALAssetsFilter *)filter过滤照片或者视频详情见ALAssetsFilter

 

(3) ALAsset

ALAsset就是一个资源文件,一个ALAssetsGroup下会有多个资源文件,获取相册和视频就是通过ALAssetsLibrary遍历得到相册ALAssetsGroup,

然后通过ALAssetsGroup遍历得到资源文件ALAsset

 

通过valueForProperty:获取资源文件的信息:

//查看资源的文件类型

[asset valueForProperty:ALAssetPropertyType]

 //查看资源的文件类型

[asset valueForProperty:ALAssetPropertyType]

 //查看资源的地理位置信息
 [asset valueForProperty:ALAssetPropertyLocation]
 //如果资源是视频,查看视频的时长
  [asset valueForProperty:ALAssetPropertyDuration]
 //查看资源的方向,图片的旋转方向
 [asset valueForProperty:ALAssetPropertyOrientation]
  //查看资源的创建时间
 [asset valueForProperty:ALAssetPropertyDate]
  //查看资源的描述信息
  [asset valueForProperty:ALAssetPropertyRepresentations]
  //查看资源的url路径
  [asset valueForProperty:ALAssetPropertyAssetURL]

 

通过 asset.defaultRepresentation 可以获取资源文件的url、size、name等信息

// 获取资源文件url

asset.defaultRepresentation.url

// 获取资源文件大小

asset.defaultRepresentation.size

// 获取资源文件名称

asset.defaultRepresentation.filename

 

(4) ALAssetsFilter

ALAssetsFilter主要用于过滤图片和视频

 

通过setAssetsFilter:筛选资源文件

//筛选图片和视频

[group setAssetsFilter:[ALAssetsFilter allAssets]];

 //筛选图片

 [group setAssetsFilter:[ALAssetsFilter allPhotos]];

 //筛选视频

 [group setAssetsFilter:[ALAssetsFilter allVideos]];

 

(5) ALAssetRepresentation

 ALAsset类有一个defaultRepresentation方法,返回值是ALAssetRepresentation类,该类的作用就是获取该资源图片的详细资源信息。

 

通过representation 获取资源文件信息

// //获取资源图片的详细资源信息

ALAssetRepresentation* representation = [asset defaultRepresentation];

//获取资源图片的长宽

CGSize dimension = [representation dimensions];

 //获取资源图片的高清图

[representation fullResolutionImage];

//获取资源图片的全屏图

[representation fullScreenImage];

//获取资源图片的名字

NSString* filename = [representation filename]; NSLog(@"filename:%@",filename);

//缩放倍数

[representation scale];

//图片资源容量大小

[representation size];

//图片资源原数据  

[representation metadata];

//旋转方向

[representation orientation];  

//资源图片url地址,该地址和ALAsset通过ALAssetPropertyAssetURL获取的url地址是一样的

 [representation url];

//资源图片uti,唯一标示符

[representation UTI]

 

2、框架使用

(1)遍历得到图片视频资源

 

(2)在系统相册中创建相册

- (void)createAlbumInPhone

{

    ALAssetsLibrary *assetsLibrary = [[ALAssetsLibrary alloc] init];

    NSMutableArray *groups=[[NSMutableArray alloc]init];

    ALAssetsLibraryGroupsEnumerationResultsBlock listGroupBlock = ^(ALAssetsGroup *group, BOOL *stop) {

        if (group) {

            [groups addObject:group];

        } else {

            BOOL haveHDRGroup = NO;

            for (ALAssetsGroup *gp in groups) {

                NSString *name =[gp valueForProperty:ALAssetsGroupPropertyName];

                if ([name isEqualToString:@"联系家庭云"]) {

                    haveHDRGroup = YES;

                }

            }

            if (!haveHDRGroup) {

                [assetsLibrary addAssetsGroupAlbumWithName:@"联系家庭云" resultBlock:^(ALAssetsGroup *group) {

                     [groups addObject:group];

                 } failureBlock:nil];

                haveHDRGroup = YES;

            }

        }

    };

    //创建相簿

    [assetsLibrary enumerateGroupsWithTypes:ALAssetsGroupAlbum usingBlock:listGroupBlock failureBlock:nil];

}

 

(3)在系统相册中保存图片

 

- (void)saveImageToAlbum:(UIImage *)image

 

{

 

    [self saveToAlbumWithMetadata:nil imageData:UIImageJPEGRepresentation(image,1.0) customAlbumName:@"联系家庭云" completionBlock:^{

 

        // 创建成功执行成功代码

 

      

 

    } failureBlock:^(NSError *error) {

 

        //处理添加失败的方法显示alert让它回到主线程执行,不然那个框框死活不肯弹出来

 

        dispatch_async(dispatch_get_main_queue(), ^{

 

            //添加失败一般是由用户不允许应用访问相册造成的,这边可以取出这种情况加以判断一下

 

            if([error.localizedDescription rangeOfString:@"User denied access"].location != NSNotFound ||[error.localizedDescription rangeOfString:@"用户拒绝访问"].location!=NSNotFound){

 

                UIAlertView *alert=[[UIAlertView alloc]initWithTitle:error.localizedDescription message:error.localizedFailureReason delegate:nil cancelButtonTitle:NSLocalizedString(@"ok", nil) otherButtonTitles: nil];

                [alert show];

            }

        });

    }];

}

 

- (void)saveToAlbumWithMetadata:(NSDictionary *)metadata imageData:(NSData *)imageData customAlbumName:(NSString *)customAlbumName completionBlock:(void (^)(void))completionBlock failureBlock:(void (^)(NSError *error))failureBlock

{

     ALAssetsLibrary *assetsLibrary = [[ALAssetsLibrary alloc] init];

    void (^AddAsset)(ALAssetsLibrary *, NSURL *) = ^(ALAssetsLibrary *assetsLibrary, NSURL *assetURL) {

        [assetsLibrary assetForURL:assetURL resultBlock:^(ALAsset *asset) {

            [assetsLibrary enumerateGroupsWithTypes:ALAssetsGroupAll usingBlock:^(ALAssetsGroup *group, BOOL *stop) {

                 if ([[group valueForProperty:ALAssetsGroupPropertyName] isEqualToString:customAlbumName]) {

                     [group addAsset:asset];

                    if (completionBlock) {

                        completionBlock();

                    }

                }

            } failureBlock:^(NSError *error) {

                if (failureBlock) { 

                    failureBlock(error); 

                }

            }];

        } failureBlock:^(NSError *error) {

            if (failureBlock) {

                 failureBlock(error);

            }

        }];

    };

    [assetsLibrary writeImageDataToSavedPhotosAlbum:imageData metadata:metadata completionBlock:^(NSURL *assetURL, NSError *error) {

    if (customAlbumName) {

           [assetsLibrary addAssetsGroupAlbumWithName:customAlbumName resultBlock:^(ALAssetsGroup *group) {

                if (group) {

                    [assetsLibrary assetForURL:assetURL resultBlock:^(ALAsset *asset) {

                         [group addAsset:asset];

                        if (completionBlock) {

                            completionBlock();

                        }

                    } failureBlock:^(NSError *error) {

                        if (failureBlock) {

                            failureBlock(error);

                        }

                    }];

                } else {

                    AddAsset(assetsLibrary, assetURL);

                }

            } failureBlock:^(NSError *error) {

                 AddAsset(assetsLibrary, assetURL);

            }];

        } else {

            if (completionBlock) {

                completionBlock();

            }

        }

    }];

}

 

以上是关于iOS中获取系统相册中的图片的主要内容,如果未能解决你的问题,请参考以下文章

iOS APP删除系统相册中选中的图片-姬云鹏

iOS--app自定义相册--从自定义的相册中获取图片

iOS开发之获取系统相册ALAssetLibrary

iOS 使用AFN 进行单图和多图上传 摄像头/相册获取图片,压缩图片

修正iOS从照相机和相册中获取的图片 方向

ios怎么把webm保存到相册