获取IOS系统相册中的照片
在iOS中,我们调用摄像头和选择相册中的资源,我们可以使用:UIImagePickerController类来完成。
当然,我们也可以不使用UI的形式来访问iOS设备的相册资源。
那就是使用:ALAssetsLibrary
可以说,是一个桥梁吧。连接了我们应用程序和相册之间的访问。
ALAssetsLibrary提供了我们对iOS设备中的相片、视频的访问。
具体方法如下:
1 导入框架 AssetLibrary
// 这个头文件
#import <AssetsLibrary/AssetsLibrary.h>
2.流程:取得数据库(AssetsLibarary),遍历数据库得到所有相册(ALAssetsGroup),然后,遍历每个相册,得到图片(ALAsset)
//1.把整个相册看做一个数据库 --对应着ALAssetsLibarary
//2.然后是相册库中的文件夹 --对应着ALAssetsGroup
//3.然后就是具体的照片或者视频 --对应着ALAsset
//拿到相册库,然后拿到文件夹,然后拿到具体照片
ALAssetsLibrary * libary= [[ALAssetsLibrary alloc]init];
/*
1.通告相册库,遍历出所有的文件夹ALAssetsGroup
<#(ALAssetsGroupType)#> 我们使用最后一个
ALAssetsGroupLibrary // The Library group that includes all assets.
ALAssetsGroupAlbum // All the albums synced from iTunes or created on the device.
ALAssetsGroupEvent // All the events synced from iTunes.
ALAssetsGroupFaces
ALAssetsGroupAll //The same as ORing together all the available group types,
第二个是 usingBlock,有多少文件夹,就会调用多少次次这个blcok,每次
调用block会将对应的文件夹group对象传过来
第三个是 失败之后调用的block
*/
// ALAssetsGroupAll 取得全部类型
[libary enumerateGroupsWithTypes: ALAssetsGroupAllusingBlock:^(ALAssetsGroup *group, BOOL *stop) {
//但是这个group有可能为空,所以判断一下
if(group != Nil)
{
//2.再通告文件夹遍历其中的资源文件
[group enumerateAssetsUsingBlock:^(ALAsset *result, NSUInteger index, BOOL *stop) {
//index就是他的位置
//ALAsset 的这个result 就是我们要的图片
//两种情况
//单选的话,这个界面是自带的
//多选的话,没有提供界面,但是提供了照片的资源,我们可以创建一个tableview来弄
//这个地方我们一般是找一个model或者数组来接受
//用数组保存起来
[_dataArr addObject:result];
}];
}
} failureBlock:^(NSError *error) {
}];
}
3.用一个tableView 来读取数据
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return _dataArr.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell * cell = [tableView dequeueReusableCellWithIdentifier:@"identifier"];
if(cell == nil)
{
cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"identifier"];
//取出数据
ALAsset *asset = [_dataArr objectAtIndex:indexPath.row];
NSString * type = [asset valueForProperty:ALAssetPropertyType];
//这是总体的类型
// 这个类型不只是图片。还可能是视频,所以判断一下
if([type isEqualToString:ALAssetTypePhoto])
{
cell.textLabel.text = @"照片";
}else if([type isEqualToString:ALAssetTypeVideo])
{
cell.textLabel.text = @"视频";
}else if([type isEqualToString:ALAssetTypeUnknown])
{
cell.textLabel.text = @"未知类型";
}
//取得缩略图
CGImageRef cmimg = [asset thumbnail];
UIImage * img = [UIImage imageWithCGImage:cmimg];
cell.imageView.image = img;
}
return cell;
}
4.取出图片
ALAssetRepresentation *rap = [asset defaultRepresentation];
//还可以取得fullScreenImage 特大图
CGImageRef ref = [rap fullResolutionImage];
UIImage * img = [UIImage imageWithCGImage:ref];
5.注意:
1. The lifetimes of objectsyou get back from a library instance are tied to the lifetime of the libraryinstance. 通过ALAssetsLibrary对象获取的其他对象只在该ALAssetsLibrary对象生命期内有效,若ALAssetsLibrary对象被销毁,则其他从它获取的对象将不能被访问,否则会有错误。具体方法:ARC和非ARC区别,ARC的时候,需要将ALAssetsLibrary * libary定义为全局
MRC的时候,libary不能release
2. ALAssetRepresentation的 metadata 方法很慢,我在iPhone4 iOS5.1.1中测试,此方法返回需要40-50ms,所以获取图片的个各种属性尽量直接从ALAssetRepresentation中获取,不要读取metadata。 这里 给出了一个此方法占用内存过多的解释,调用多次也确实很容易会memory warning,或许也能解析其为什么很慢吧。
3. 系统”相册”程序显示的图片是 fullScreenImage ,而不是fullResolutionImage ,fullResolutionImage尺寸太大,在手机端显示推荐用fullScreenImage。
fullScreenImage已被调整过方向,可直接使用
[UIImage imageWithCGImage:representation.fullScreenImage];
使用fullResolutionImage要自己调整方法和scale,即
[UIImage imageWithCGImage:representation.fullResolutionImage scale:representation.scale orientation:representation.orientation];
4.遍历Assets Group
使用 enumerateGroupsWithTypes:usingBlock:failureBlock: 方法可遍历assets group;
此方法为异步执行,若之前未被授权过,此方法会向用户请求访问数据的权限;若用户拒绝授权或其他错误则会执行failureBlock;
如果用户关掉了位置服务(Location Services,在设置->通用中),返回的错误为ALAssetsLibraryAccessGloballyDeniedError 。
enumerationBlock和failureBlock与在调用此方法的线程内执行,若要在背景线程进行遍历,可将遍历代码放入GCD或NSOperation中。
5.遍历Assets Group中的Assets
使用 enumerateAssetsUsingBlock: 方法或者其他遍历方法可遍历ALAssetsGroup中的所有ALAsset;
可通过 setAssetsFilter: 设置过滤器( ALssetsFilter )使enumerateAssetsUsingBlock:只返回特定类型asset,而 numberOfAssets 只返回特定类型asset的数量。 可以设置只显示Photo( allPhotos ),只显示Video( allVideos ),或显示全部(allAssets )。
enumerateAssetsUsingBlock:为同步方法,只有所有Asset遍历完才返回。所以需要将遍历代码放入背景线程,防止阻塞UI线程。
6.根据url获取asset
使用ALAssetsLibrary的 assetForURL:resultBlock:failureBlock: 方法,可根据之前从ALAssetRepresentation中获取的url重新获取ALAsset对象,此方法同enumerateGroupsWithTypes:usingBlock:failureBlock:一样为异步方法。
6.获取Assets的各种属性
1. 相册封面图片 [assetsGroup posterImage ];
2. 照片url[[[asset defaultRepresentation] url]absoluteString];
3. 照片缩略图 [asset thumbnail]; [assetaspectRatioThumbnail];
4. 照片全尺寸图 [[asset defaultRepresentation]fullResolutionImage];
5. 照片全屏图 [[asset defaultRepresentation]fullScreenImage];
6. 照片创建时间 [assetvalueForProperty:ALAssetPropertyDate];
7. 照片拍摄位置(可能为nil) [assetvalueForProperty:ALAssetPropertyLocation];
8. 照片尺寸 [[asset defaultRepresentation]dimensions];