美文网首页
iOS Photos库的使用

iOS Photos库的使用

作者: 第九号线 | 来源:发表于2018-01-05 09:46 被阅读138次

    说明

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

    一、<Photos/Photos.h>,对象说明

    • 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库的使用

          本文链接:https://www.haomeiwen.com/subject/gpdjnxtx.html