获取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];