iOS Photos库的使用

说明

在iOS8以后,AssetsLibrary被弃用,苹果要求用Photos。查了一些资料,比较系统的使用Photos库的文章不是很多,这里总结一下。

一、,对象说明

  • PHAsset:媒体资源对象,可能是图片,或者视频;
  • PHAssetCollection:相簙对象,包含一个相册的所有信息;
  • PHImageManager:图片管理,一个单例,可以通过asset获取图片;
  • PHImageRequestOptions:图片请求选项;
  • PHFetchResult:查找的结果;
  • PHFetchOptions:查找请求的选项;

二、获取系统相册

__block BOOL showAlbums = YES;
WYPhotoLibraryController *library = (WYPhotoLibraryController *)self.navigationController;

//iOS8以后,使用PHAsset
PHFetchOptions *fetchOptions = [[PHFetchOptions alloc] init];

//获取所有系统相册
PHFetchResult *smartAlbumsFetchResult = [PHAssetCollection fetchAssetCollectionsWithType:PHAssetCollectionTypeSmartAlbum subtype:PHAssetCollectionSubtypeAlbumRegular options:fetchOptions];
//遍历相册
[smartAlbumsFetchResult enumerateObjectsUsingBlock:^(PHAssetCollection *collection, NSUInteger idx, BOOL *stop) {
    showAlbums = NO;
    PHFetchOptions *fetchOptionsAlbums = [[PHFetchOptions alloc] init];
    
    //通过设置选择器,获取需要的资源
    switch (library.photoFilterType) {
        case WYPhotoFilterAllImage:
            fetchOptionsAlbums.predicate = [NSPredicate predicateWithFormat:@"mediaType == %d", PHAssetMediaTypeImage];
            break;
        case WYPhotoFilterAllVideo:
            fetchOptionsAlbums.predicate = [NSPredicate predicateWithFormat:@"mediaType == %d", PHAssetMediaTypeVideo];
            break;
        default:
            break;
    }
    
    //有可能是PHCollectionList,会造成crash,过滤掉
    if ([collection isKindOfClass:[PHAssetCollection class]]) {
        //从相册中获取数据
        PHFetchResult *fetchResult = [PHAsset fetchAssetsInAssetCollection:collection options:fetchOptionsAlbums];
        //去掉视频、最近删除、最近添加
        if (![collection.localizedTitle isEqualToString:@"Recently Deleted"] &&
            ![collection.localizedTitle isEqualToString:@"Recently Added"] &&
            ![collection.localizedTitle isEqualToString:@"Videos"]) {
            if (fetchResult.count > 0) {
                WYPhotoGroup *group = [[WYPhotoGroup alloc] init];
                group.groupName = collection.localizedTitle;
                group.count = fetchResult.count;
                group.assetCollection = collection;
                group.fetchResult = fetchResult;
                [self.photoGroups addObject:group];
            }
        }
    }
}];

三、获取自定义相册

//获取所有自定义相册
PHFetchResult *userAlbumsFetchResult = [PHAssetCollection fetchAssetCollectionsWithType:PHAssetCollectionTypeAlbum subtype:PHAssetCollectionSubtypeSmartAlbumUserLibrary options:fetchOptions];
//遍历相册
[userAlbumsFetchResult enumerateObjectsUsingBlock:^(PHAssetCollection *collection, NSUInteger idx, BOOL *stop) {
    showAlbums = NO;
    PHFetchOptions *fetchOptionsAlbums = [[PHFetchOptions alloc] init];
    
    switch (library.photoFilterType) {
        case WYPhotoFilterAllImage:
            fetchOptionsAlbums.predicate = [NSPredicate predicateWithFormat:@"mediaType == %d", PHAssetMediaTypeImage];
            break;
        case WYPhotoFilterAllVideo:
            fetchOptionsAlbums.predicate = [NSPredicate predicateWithFormat:@"mediaType == %d", PHAssetMediaTypeVideo];
            break;
        default:
            break;
    }
    
    PHFetchResult *fetchResult = [PHAsset fetchAssetsInAssetCollection:collection options:fetchOptionsAlbums];
    if (fetchResult.count > 0) {
        WYPhotoGroup *group = [[WYPhotoGroup alloc] init];
        group.groupName = collection.localizedTitle;
        group.count = fetchResult.count;
        group.assetCollection = collection;
        group.fetchResult = fetchResult;
        [self.photoGroups addObject:group];
    }
}];

四、获取相册的封面(相册中的最后一张图片)

- (void)setGetThumbnail:(void (^)(UIImage *))getThumbnail {
    _getThumbnail = getThumbnail;

    //如果有相册的封面缓存图片,直接使用
    if (_cacheThumbImage) {
        _getThumbnail(_cacheThumbImage);
        return;
    }
    //获取封面
    if ([_assetCollection isKindOfClass:[PHCollection class]]) {
        //定义一个查找结果
        if (!_fetchResult) {
            PHFetchOptions *fetchOptions = [[PHFetchOptions alloc] init];
            _fetchResult = [PHCollection fetchCollectionsInCollectionList:_assetCollection options:fetchOptions];
        }
    
        PHFetchResult *tmpFetchResult = _fetchResult;
        //获取最后一个查找资源
        PHAsset *tmpAsset = [tmpFetchResult objectAtIndex:tmpFetchResult.count - 1];
    
        //获取图片,并剪切
        PHImageRequestOptions *requestOptions = [[PHImageRequestOptions alloc] init];
        requestOptions.deliveryMode = PHImageRequestOptionsDeliveryModeOpportunistic;
        requestOptions.resizeMode = PHImageRequestOptionsResizeModeExact;
        [[PHImageManager defaultManager] requestImageForAsset:tmpAsset targetSize:CGSizeMake(200, 200) contentMode:PHImageContentModeAspectFill options:requestOptions resultHandler:^(UIImage * _Nullable result, NSDictionary * _Nullable info) {
            BOOL download = ![info[PHImageCancelledKey] boolValue] && ![info[PHImageErrorKey] boolValue] && ![info[PHImageResultIsDegradedKey] boolValue];
        
            if (download) {
                float scale = result.size.height / kThumbImageHeight;
                _cacheThumbImage = [UIImage imageWithCGImage:result.CGImage scale:scale orientation:UIImageOrientationUp];
                _getThumbnail(_cacheThumbImage);
            }
        }];
    }
}

五、遍历相册中的所有资源,并封装对象

 - (void)enumerateObjectsUsingBlock:(void (^)(id obj, NSUInteger idx, BOOL *stop))block {
    if (_assetCollection) {
        if ([_assetCollection isKindOfClass:[PHCollection class]]) {
            if (!_fetchResult) {
                PHFetchOptions *tmpFetchOptions = [[PHFetchOptions alloc] init];
                _fetchResult = [PHCollection fetchCollectionsInCollectionList:_assetCollection options:tmpFetchOptions];
            }
            [(PHFetchResult *) _fetchResult enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
                if (obj) {
                    WYPhoto *photo = [[WYPhoto alloc] init];
                    photo.asset = obj;
        
                    [weakSelf.photos addObject:photo];
                }
    
              if (weakSelf.group.count-1 ==idx) {
                  [weakSelf.collectionView reloadData];
              }
          }];
        }
    }
}

六、获得一个资源(PHAsset)的文件大小

- (void)setGetFileSize:(void (^)(NSInteger))getFileSize {
     _getFileSize = getFileSize;

    if (_asset) {
        if (_cacheFileSize > 0) {
            _getFileSize(_cacheFileSize);
            return;
        }
    
        //视频资源和图片资源获取文件大小的方式不同
        if (self.mediaType == WYPhotoMediaTypeVideo) {
            PHVideoRequestOptions *options = [[PHVideoRequestOptions alloc] init];
            [[PHImageManager defaultManager] requestAVAssetForVideo:_asset options:options resultHandler:^(AVAsset * _Nullable asset, AVAudioMix * _Nullable audioMix, NSDictionary * _Nullable info) {
                if ([asset isKindOfClass:[AVURLAsset class]]) {
                    AVURLAsset *urlAsset = (AVURLAsset *)asset;
                    NSNumber *size;
                
                    [urlAsset.URL getResourceValue:&size forKey:NSURLFileSizeKey error:nil];
                    _cacheFileSize = [size floatValue]; // _cacheFileSize / (1024 * 1024) 转MB
                    _getFileSize(_cacheFileSize);
                }
            }];
        }else {
            [[PHImageManager defaultManager] requestImageDataForAsset:_asset options:nil resultHandler:^(NSData * _Nullable imageData, NSString * _Nullable dataUTI, UIImageOrientation orientation, NSDictionary * _Nullable info) {
                _cacheFileSize = imageData.length; // _cacheFileSize / (1024 * 1024) 转MB
                _getFileSize(_cacheFileSize);
            }];
        }
    }
}

七、获得一个资源(PHAsset)的缩略图

- (void)setGetThumbnail:(void (^)(UIImage *))getThumbnail {
    _getThumbnail = getThumbnail;

    if (_asset) {
        if (_cacheThumbImage) {
            _getThumbnail(_cacheThumbImage);
            return;
        }
    
        if ([_asset isKindOfClass:[PHAsset class]]) {
            PHImageRequestOptions *requestOptions = [[PHImageRequestOptions alloc] init];
            requestOptions.deliveryMode = PHImageRequestOptionsDeliveryModeOpportunistic;
            requestOptions.resizeMode = PHImageRequestOptionsResizeModeExact;
            [[PHImageManager defaultManager] requestImageForAsset:_asset targetSize:CGSizeMake(200, 200) contentMode:PHImageContentModeAspectFill options:requestOptions resultHandler:^(UIImage * _Nullable result, NSDictionary * _Nullable info) {
                BOOL download = ![info[PHImageCancelledKey] boolValue] && ![info[PHImageErrorKey] boolValue] && ![info[PHImageResultIsDegradedKey] boolValue];
            
                if (download) {
                    _cacheThumbImage = result;
                    _getThumbnail(_cacheThumbImage);
                }
            }];
        }
    }
}

八、获得一个资源(PHAsset)的高清图

- (void)setGetFullImage:(void (^)(UIImage *))getFullImage {
    _getFullImage = getFullImage;

    if (_asset) {
        if (_cacheFullImage) {
            _getFullImage(_cacheFullImage);
            return;
        }
    
        if ([_asset isKindOfClass:[PHAsset class]]) {
            PHImageRequestOptions *requestOptions = [[PHImageRequestOptions alloc] init];
            requestOptions.deliveryMode = PHImageRequestOptionsDeliveryModeOpportunistic;
            requestOptions.resizeMode = PHImageRequestOptionsResizeModeExact;
        
            //图的宽度
            CGFloat photoWidth = [UIScreen mainScreen].bounds.size.width;
            //图宽高比
            CGFloat aspectRatio = ((PHAsset*)_asset).pixelWidth / (CGFloat)((PHAsset*)_asset).pixelHeight;
            //屏幕分辨率 
            //[[UIScreen main] scale] == 1; //代表320 x 480 的分辨率
            //[[UIScreen main] scale] == 2; //代表640 x 960 的分辨率
            //[[UIScreen main] scale] == 3; //代表1242 x 2208 的分辨率
            CGFloat multiple = [UIScreen mainScreen].scale;
            //图宽度,像素
            CGFloat pixelWidth = photoWidth * multiple;
            //图高度,像素
            CGFloat pixelHeight = pixelWidth / aspectRatio;
        
            //允许从iCloud上下载
            requestOptions.networkAccessAllowed = YES;
            requestOptions.progressHandler = ^(double progress, NSError * _Nullable error, BOOL * _Nonnull stop, NSDictionary * _Nullable info) {
                if (self.getNetworkProgressHandler) {
                    self.getNetworkProgressHandler(progress, error, stop, info);
                }
            };
        
            [[PHImageManager defaultManager] requestImageForAsset:_asset targetSize:CGSizeMake(pixelWidth, pixelHeight) contentMode:PHImageContentModeAspectFill options:requestOptions resultHandler:^(UIImage * _Nullable result, NSDictionary * _Nullable info) {
                BOOL download = ![info[PHImageCancelledKey] boolValue] && ![info[PHImageErrorKey] boolValue] && ![info[PHImageResultIsDegradedKey] boolValue];
            
                if (download) {
                    _cacheFullImage = result;
                    _getFullImage(_cacheFullImage);
                }
            }];
        }
    }
}

九、完整代码,请看:传送门。

你可能感兴趣的:(iOS Photos库的使用)