使用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即可引入,如下图所示:
引入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…最终效果如下所示:
图片浏览器

0 0
原创粉丝点击