xcode 8的到来意味着ios8以下的要慢慢的被抛弃了,所有我在这里写了一个多选图片的Demo.(多选图片的Demo网上有很多了,我只是把自己学到的东西跟大家交流交流,请不要太认真哦)
在这里我就不说AssetsLibrary了
- PhotoKit属性介绍
PHAsset 代表照片库中的一个资源,通过PHAsset可以获取和保存资源。(白话就是:你想要图片就要用他去取)
PHFetchOptions 获取资源时的参数,可以传Nil,系统会有默认值。
PHAssetCollection: PHCollecion的子类,表示一个时刻或者一个相册。
PHFetchResult:表示一系列的资源结果集合,也可以是相册的集合。
PHImageManager: 用于处理资源的加载,加载图片的过程带有缓存处理,可以通过传入一个 PHImageRequestOptions 控制资源的输出尺寸等 规格
PHImageRequestOptions: 如上面所说,控制加载图片时的一系列参数
获取用户相册
PHFetchOptions *fetchOptions = [[PHFetchOptions alloc] init];//这里可以不用创建
//PHAssetCollectionTypeSmartAlbum 表示智能相册 PHAssetCollectionSubtypeAlbumRegular 用户创建所有的相册
PHFetchResult *smartAlbumsFetchResult = [PHAssetCollection fetchAssetCollectionsWithType:PHAssetCollectionTypeSmartAlbum subtype:PHAssetCollectionSubtypeAlbumRegular options:fetchOptions];
//注意类型
for (PHAssetCollection *sub in smartAlbumsFetchResult){
//遍历到数组中
PHFetchResult *group = [PHAsset fetchAssetsInAssetCollection:sub options:nil];
//过滤掉没有图片的Group
if (group.count > 0) {
[self.groupList addObject:sub];
}
}
PHAssetCollectionTypeSmartAlbum 表示智能相册
PHAssetCollectionTypeAlbum表示专辑
PHAssetCollectionTypeMoment表示时刻
PHAssetCollectionSubtypeAlbumRegular 用户在 Photos 中创建的相册
PHAssetCollectionSubtypeSmartAlbumPanoramas 相机拍摄的全景照片
PHAssetCollectionSubtypeSmartAlbumBursts 连拍模式拍摄的照片
PHAssetCollectionSubtypeSmartAlbumUserLibrary 所有的照片都会在这里面
显示用户的相册(获取最后一张图片)
@property (nonatomic, strong) PHFetchResult *group;
[[PHImageManager defaultManager] requestImageForAsset:group.lastObject targetSize:CGSizeMake(screen_width,screen_height) contentMode:PHImageContentModeAspectFit options:nil resultHandler:^(UIImage *result, NSDictionary *info) {
_imageView.image = result;
}];
显示相册名和图片的数量
PHAssetCollection *_titleAsset;
- (void)setGroupList:(NSMutableArray *)groupList{
_groupList = groupList;
_titleAsset = [_groupList objectAtIndex:_row];
//显示相薄名称+图片张数
_textLabel.text = [NSString stringWithFormat:@"%@(%zi张)",[NSString stringWithFormat:@"%@",_titleAsset.localizedTitle], _group.count];
[_textLabel sizeToFit];
}
获取到某个相册的所有图片(我是用collectionView来展示的)
- 设置数据源
NSMutableArray *photoList = [[NSMutableArray alloc] init];
//把数据封装成一个模型 方便以后使用
for (PHAsset *asset in _group) {
if (asset.mediaType == PHAssetMediaTypeImage) {
PhotoModel *model = [[PhotoModel alloc] init];
model.asset = asset;
//获取缩略图大小
CGFloat scale = screen_width / screen_height;
CGSize resize = CGSizeMake(asset.pixelWidth * scale, asset.pixelHeight * scale);
model.thumbSize = CGSizeMake(_collectionView.frame.size.height / resize.height * resize.width, _collectionView.frame.size.height);
[photoList addObject:model];
}
}
_assetList = [NSMutableArray arrayWithArray:[photoList reverseObjectEnumerator].allObjects];
- 展示数据
注意几个方面
1.也就是用模型的好处,我拿到了高清的图片就把它添加到模型里 面,下次就不需要在去加载了。
2.在说一下resizeMode的作用,esizeMode 属性控制图像的剪裁,
PHImageRequestOptionsResizeModeExact 则返回图像必须和目标大小相匹配,并且图像质量也为高质量图像
PHImageRequestOptionsResizeModeFast 则请求的效率更高,但返回的图像可能和目标大小不一样并且质量较低。
PHImageRequestOptionsResizeModeNone 没有大小
我这里选择PHImageRequestOptionsResizeModeFast是因为我只需要加载的效率。
还有其他的属性我就不一一的说了。
- (void)setModel:(PhotoModel *)model {
_model = model;
_imageView.frame = self.bounds;
if (_model.image) {
_imageView.image = _model.image;
}else{
PHImageRequestOptions *options = [[PHImageRequestOptions alloc] init];
options.resizeMode = PHImageRequestOptionsResizeModeExact;
options.deliveryMode = PHImageRequestOptionsDeliveryModeOpportunistic;
[[PHImageManager defaultManager] requestImageForAsset:_model.asset targetSize:CGSizeMake(screen_width, screen_height) contentMode:PHImageContentModeAspectFit options:options resultHandler:^(UIImage * _Nullable result, NSDictionary * _Nullable info) {
NSLog(@"%@",result);
// //判断是否是高清的图片
BOOL downloadFinined = ![[info objectForKey:PHImageCancelledKey] boolValue] && ![info objectForKey:PHImageErrorKey] && ![[info objectForKey:PHImageResultIsDegradedKey] boolValue];
if (_model == model) {
if (downloadFinined) {
_model.image = result;
}
_model.thumbImage = result;
_imageView.image = result;
}
}];
}
}
图片游览 之前我用的是ScrolleView写,以后发现用collectionView写更好一些,代码也少很多。
重要的代码都在collectionViewCell里面
- (instancetype)initWithFrame:(CGRect)frame{
if (self = [super initWithFrame:frame]) {
_scrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(5, 0, frame.size.width - 10, frame.size.height)];
_scrollView.delegate = self;
_scrollView.backgroundColor = [UIColor redColor];
_scrollView.minimumZoomScale = 1;
_scrollView.maximumZoomScale = 2.8;
_scrollView.showsHorizontalScrollIndicator = NO;
[self.contentView addSubview:_scrollView];
UITapGestureRecognizer *singleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(singleTapEvent)];
[_scrollView addGestureRecognizer:singleTap];
UITapGestureRecognizer *doubleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(doubleTapEvent:)];
doubleTap.numberOfTapsRequired = 2;
[_scrollView addGestureRecognizer:doubleTap];
[singleTap requireGestureRecognizerToFail:doubleTap];
_imageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, _scrollView.frame.size.width, _scrollView.frame.size.height)];
[_scrollView addSubview:_imageView];
}
return self;
}
- (void)setModel:(PhotoModel *)model{
_model = model;
if (_model.image) {
_imageView.image = _model.image;
}else{
[[PHImageManager defaultManager] requestImageForAsset:_model.asset targetSize:CGSizeMake(screen_width, screen_height) contentMode:PHImageContentModeAspectFit options:nil resultHandler:^(UIImage * _Nullable result, NSDictionary * _Nullable info) {
BOOL downloadFinined = ![[info objectForKey:PHImageCancelledKey] boolValue] && ![info objectForKey:PHImageErrorKey] && ![[info objectForKey:PHImageResultIsDegradedKey] boolValue];
if (_model == model) {
if (downloadFinined) {
_model.image = result;
_imageView.image = _model.image;
}else{
_model.thumbImage = result;
_imageView.image = result;
}
}
}];
}
[self setImageFrame];
}
- (void)setImageFrame{
UIImage *image = _imageView.image;
CGFloat scale = 0;
if (image && image.size.width > 0) {
scale = [UIScreen mainScreen].bounds.size.width / image.size.width;
}
CGRect frame = _imageView.frame;
frame.size.width = [UIScreen mainScreen].bounds.size.width;
frame.size.height = scale * image.size.height;
frame.origin.x = 0;
if (frame.size.height > self.frame.size.height) {
frame.origin.y = 0;
}else{
frame.origin.y = (self.frame.size.height - frame.size.height) / 2;
}
_imageView.frame = frame;
}
- (void)zoomToMinimumScale{
[_scrollView setZoomScale:_scrollView.minimumZoomScale animated:YES];
}
#pragma mark - ---------------------- UIScrollViewDelegate
- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView {
return _imageView;
}
- (void)scrollViewDidEndZooming:(UIScrollView *)scrollView withView:(UIView *)view atScale:(CGFloat)scale {
if (scrollView.zoomScale > scrollView.maximumZoomScale){
[scrollView setZoomScale:scrollView.maximumZoomScale animated:YES];
}
}
- (void)scrollViewDidZoom:(UIScrollView *)scrollView {
//放大过程中需要设置图片的中心点
CGFloat offsetX = (scrollView.bounds.size.width > scrollView.contentSize.width) ? (scrollView.bounds.size.width - scrollView.contentSize.width)/2 : 0.0;
CGFloat offsetY = (scrollView.bounds.size.height > scrollView.contentSize.height)?(scrollView.bounds.size.height - scrollView.contentSize.height)/2 : 0.0;
_imageView.center = CGPointMake(scrollView.contentSize.width/2 + offsetX,scrollView.contentSize.height/2 + offsetY);
}
#pragma mark - ---------------------- 事件
- (void)singleTapEvent{
if (self.collectionViewCellDelgate && [self.collectionViewCellDelgate respondsToSelector:@selector(hidenPhotoBrowse)]) {
[self.collectionViewCellDelgate hidenPhotoBrowse];
}
}
- (void)doubleTapEvent:(UITapGestureRecognizer *)sender{
if (_scrollView.zoomScale != _scrollView.minimumZoomScale) {
[_scrollView setZoomScale:_scrollView.minimumZoomScale animated:YES];
}else{
//放大倍数
CGFloat scale = _scrollView.maximumZoomScale;
CGFloat newWidth = _scrollView.bounds.size.width / scale;
CGFloat newHeight = _scrollView.bounds.size.height / scale;
//获取双击的点
CGFloat touchX = [sender locationInView:sender.view].x;
CGFloat touchY = [sender locationInView:sender.view].y;
CGRect frame = CGRectMake(touchX - newWidth/2, touchY - newHeight/2, newWidth, newHeight);
[_scrollView zoomToRect:frame animated:YES];
}
}
基本上重点的我都说了,下面说一下我在做的时候出现的问题吧。之前我用过异步去加载数据源为了解决卡顿的问题,卡顿会在1000张以上的时候出现。用异步就出问题,Photokit本身就有同步和异步,synchronous这个属性就是是否同步。多选图片这要的问题就图片加载的时候,出现的卡顿。图片的质量。好吧,或许不是很详细。大家可以下载我的Demo看看。有什么问题可以留言给我。
https://github.com/OneGangk/SelectImageDemo 这个是我用xcode 8写的可能有些人没有更新
https://github.com/OneGangk/PhotoSelectedMore xcode 7