使用AssetsLibrary库实现系统类似照片浏览器

本文介绍了如何利用AssetsLibrary库在iOS中实现一个系统类似的照片浏览器。内容包括引入AssetsLibrary框架,理解ALAssetsGroup、ALAsset和ALAssetRepresentation的组成,检查授权,获取相册列表,从相册中获取图片,以及最终的实现效果展示。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

使用AssetsLibrary库实现系统类似照片浏览器

由于项目需求,要实现一个多项选择的图片浏览器,使用系统的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…最终效果如下所示:
图片浏览器

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值