使用AssetsLibrary库实现系统类似照片浏览器
来源:互联网 发布:java有指针吗 编辑:程序博客网 时间:2024/06/15 19:37
使用AssetsLibrary库实现系统类似照片浏览器
- 使用AssetsLibrary库实现系统类似照片浏览器
- 1AssetsLibrary的引入
- 2AssetsLibrary组成介绍
- 1AssetsLibrary
- 2ALAssetsGroup
- 3ALAsset
- 4ALAssetRepresentation
- 3图片浏览器的实现
- 1授权的检查
- 2相册列表的获取
- 3获取指定相册中的图片
- 4最终效果展示
由于项目需求,要实现一个多项选择的图片浏览器,使用系统的UIImagePickerController只能选择单张图片,于是决定通过AssetsLibrary自定义。
1、AssetsLibrary的引入
引用AssetsLibrary的方法同引入iOS系统提供的其他framework一样,在“General”下滚动至”Linked Frameworks and Libraries”或者在”Build Phases”标签页中,展开”Link Binary With Libraries”,然后点击下面的加号,在弹出的对话框中输入AssetsLibrary即可引入,如下图所示:
2、AssetsLibrary组成介绍
其实AssetsLibrary的使用非常简单,网络上也有很多关于该framework的文章,关于AssetsLibrary的介绍就引用别人写的一篇文章里的内容吧。(http://www.jianshu.com/p/14d04b3ef00a 文/TEASON) AssetsLibrary 的组成比较符合照片库本身的组成,照片库中的完整照片库对象、相册、相片都能在 AssetsLibrary 中找到一一对应的组成,这使到 AssetsLibrary 的使用变得直观而方便。
1、AssetsLibrary:
代表整个设备中的资源库(照片库),通过 AssetsLibrary 可以获取和包括设备中的照片和视频
2、ALAssetsGroup:
映射照片库中的一个相册,通过 ALAssetsGroup 可以获取某个相册的信息,相册下的资源,同时也可以对某个相册添加资源。
3、ALAsset:
映射照片库中的一个照片或视频,通过 ALAsset 可以获取某个照片或视频的详细信息,或者保存照片和视频。
4、ALAssetRepresentation:
ALAssetRepresentation 是对 ALAsset 的封装(但不是其子类),可以更方便地获取 ALAsset 中的资源信息,每个 ALAsset 都有至少有一个 ALAssetRepresentation 对象,可以通过 defaultRepresentation 获取。而例如使用系统相机应用拍摄的 RAW + JPEG 照片,则会有两个 ALAssetRepresentation,一个封装了照片的 RAW 信息,另一个则封装了照片的 JPEG 信息。
3、图片浏览器的实现
1、授权的检查
要想访问相册功能,根据iOS一惯的作风,肯定是要有授权的。如何检查授权呢?就是使用ALAssetsLibrary类中的静态方法—authorizationStatus,该方法返回一个ALAuthorizationStatus类型的值,如果该值为ALAuthorizationStatusRestricted或ALAuthorizationStatusDenied,则表明没有授权,那么我们也无法再继续下去。
2、相册列表的获取
取得授权之后,我们便可以使用ALAssetsLibrary类中常用的enumerateGroupsWithTypes:usingBlock:failureBlock:方法枚举出系统中所有的相册集,该方法接受一个参数,从方法名上也可以看出来,该参数是要求我们指定一个要枚举的相册的类型,选项有ALAssetsGroupLibrary,AlAssetsGroupAlbum,ALAssetsGroupEvent,ALAssetsGroupFaces,ALAssetsGroupSavedPhtos,ALAssetsGroupPhotoStream,ALAssetsGroupAll,根据需要传递相应的参数即可。至于usingBlock的定义是这样的:typedef void (^ALAssetsLibraryGroupsEnumerationResultsBlock)(ALAssetsGroup *group, BOOL *stop),传出的两个参数中,ALAssetsGroup代表一个相册集,stop则用于指示是否应该停止枚举。当我们取到的group为nil的时候,则表示所有的相册集已经枚举完毕,此时我们应该将*stop设置为NO,并进行后续相应的操作,如以下代码所示:
ALAuthorizationStatus authorizationStatus = [ALAssetsLibrary authorizationStatus]; if (authorizationStatus != ALAuthorizationStatusRestricted && authorizationStatus != ALAuthorizationStatusDenied) { dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ WEAKSELF; [self.assetsLibrary enumerateGroupsWithTypes:ALAssetsGroupAll usingBlock:^(ALAssetsGroup *group, BOOL *stop) { if(group) [assetsGroupArray addObject:group]; else { *stop = YES; dispatch_async(dispatch_get_main_queue(), ^{ [wself.theTableView reloadData]; }); } return ; } failureBlock:^(NSError *error) { [[[UIAlertView alloc] initWithTitle:nil message:error.localizedFailureReason delegate:nil cancelButtonTitle:I(@"确定") otherButtonTitles: nil] show]; }]; }); }else { [[[UIAlertView alloc] initWithTitle:nil message:I(@"未取得授权,无法访问相薄") delegate:nil cancelButtonTitle:I(@"确定") otherButtonTitles: nil] show]; }
考虑到可能用户的相册会有很多,如果在主线程上进行枚举的话,会导致主UI卡死,所以采用GCD在非UI线程上执行该方法,待枚举结束之后,再在主线程上更新UITableView,将所获得的ALAssetsGroup实例存入到一个NSMutableArray当中。效果如下图所示:
在UITableView的代理方法cellForRowAtIndexPath中,我们可以使用ALAssetsGroup的posterImage来获取一张封面图片,并可以使用numberOfAssets方法来获取这个相册集中共有多少张照片,同时还能使用valueForProperty方法传入ALAssetsGroupPropertyName来获取到该相册的名字,代码如下所示:
ALAssetsGroup* group = (ALAssetsGroup*)[assetsGroupArray objectAtIndex:(int)indexPath.row]; [cell.posterImageView setImage:[UIImage imageWithCGImage:group.posterImage]]; [cell.assetsTitleLabel setText:[group valueForProperty:ALAssetsGroupPropertyName]]; [cell.assetsCountLabel setText:[NSString stringWithFormat:@"%ld", (long)group.numberOfAssets]];
3、获取指定相册中的图片
同样的,我们要获取对应相册中的图片,也可以使用ALAssetsGroup中提供的常用方法enumerateAssetsUsingBlock:方法,该方法的使用方式同ALAssetsLibrary中的枚举方法一模一样,该方法在Block中会返回一个ALAsset的实例,这个实例就相当于我们相册集中的一张图片了,我们同样可以使用一个NSMutableArray来将这个实例保存下来。代码如下所示:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ WEAKSELF; [self.assetsGroup enumerateAssetsUsingBlock:^(ALAsset *result, NSUInteger index, BOOL *stop) { if(result != nil) [assetsMutableArray addObject:result]; else { *stop = YES; dispatch_async(dispatch_get_main_queue(), ^{ [wself.assetsCollectionView reloadData]; }); } }]; });
同样,出于不卡死UI线程的考虑,我们同样在非UI线程上执行枚举操作。
得到了ALAsset实例之后,图片浏览器基本上也就实现完毕了,剩下的只需要把图片从ALAsset中取出来,然后按自己需要的方式展示出来即可,那怎么从ALAsset中取出图片呢?根据我自己的实现方式,我是先展示一张缩略图,用户点击之后再做另外的操作。从ALAsset中取得缩略图的方法很简单,ALAsset类中就提供了thumbnail和aspectRatioThumbnail两个能获取到缩略图的方法,至于两个方法的区别,自己去试一试就明白了,其实我自己也没有试过,所以不好意思误导读者。用户点击之后,一般可以预览一张完整的图,那应该要怎么做呢?这就要用到ALAssetRepresentation了,我们可以通过ALAsset中的常用方法defaultRepresentation获取到该实例,该例中就提供了获取图片大小、尺寸等的方法,如果要获取原图,则可以使用其中的fullResolutionImage方法来取得一个CGImageRef,从页赋值给UIImageView进行图片展示,我使用的是一个UICollectionView来展示图片,代码如下所示:
-(UICollectionViewCell*)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath { UICollectionViewCell* cell = [collectionView dequeueReusableCellWithReuseIdentifier:IMAGEPICKERCOLLECTIONVIEWCELLIDENTIFIER forIndexPath:indexPath]; [cell.contentView.subviews makeObjectsPerformSelector:@selector(removeFromSuperview)]; UIImageView* imageView = [[UIImageView alloc] initWithFrame:cell.contentView.bounds]; [cell.contentView addSubview:imageView]; ALAsset* asset = (ALAsset*)[assetsMutableArray objectAtIndex:indexPath.row]; [imageView setImage:[UIImage imageWithCGImage:asset.aspectRatioThumbnail]]; return cell;}
4、最终效果展示
AssetsLibrary的使用方法真的是非常简单,不过从iOS8开始, Apple公司提供了PhotoKit用来替代AssetsLibrary,并在iOS9中正式弃用AssetsLibray,不过管它呢,谁让它的使用方式so easy…最终效果如下所示:
- 使用AssetsLibrary库实现系统类似照片浏览器
- AssetsLibrary显示本地照片
- iOS相册实现与AssetsLibrary框架使用
- iOS开发之:AssetsLibrary框架访问相册所有照片实现多选照片
- Android进阶:实现android系统自带查看照片动画效果 类似Gallery手势滑动
- AssetsLibrary使用介绍
- AssetsLibrary
- AssetsLibrary
- IOS AssetsLibrary框架的使用
- IOS AssetsLibrary框架的使用
- Android 横向ScrollView照片浏览器实现
- iOS 开发之照片框架详解之--AssetsLibrary
- Android 之实现类似QQ图片说说照片选择
- emacs 实现类似浏览器的页签
- 实现类似UC浏览器的菜单
- 实现类似浏览器的缩放页面比例
- html+css实现照片墙系统
- 如何实现使用C/C++直接调用系统默认浏览器?
- 安卓开发代码规范以及命名规范
- View的14个方法
- map 按value排序
- 详解C++各种智能指针: auto_ptr, shared_ptr, weak_ptr, scoped_ptr
- 安装pptpd
- 使用AssetsLibrary库实现系统类似照片浏览器
- 常用数字及模拟视频接口
- windows异常处理__try __except
- Missing Gradle Project Information
- 分布式内存网格Hazelcast源码导读
- MySQL的自然联结+外部联结(左外连接,右外连接)+内部联结
- JavaWeb开发之深入分析请求转发和重定向的应用场景以及请求包含 (跟着龙哥学JavaWeb)
- 15.7 擦除的神秘之处
- Mockito中java.lang.noclassdeffounderror android/support/v4/app/taskstackbuilder$supportparentable