Photos框架使用时发现的问题

1.加载图片方法的比较

使用从Photos框架中获取的PHAsset获取UIImage的时候,Photos框架提供了两种方法:

1)、PHImageManager的requestImageForAsset:这个方法是通过PHAsset直接获取到UIImage对象,很多人会惯用这个方法,因为获取缩略图也是使用这个方法,比较方便,获取大图也会自然而然使用这个方法,但是这个方法有一个大坑,我被困扰了好长一段时间。使用这个方法获取UIImage时,会对图片进行渲染,如果你的图片很大的时候,比如全景图,那么很大可能会导致app因为内存暴涨问题崩溃,而且获取的耗时也会增加;

2)、PHImageManager的requestImageDataForAsset:这个方法是把PHAsset转化为NSData对象返回给我们,使用NSData对象可以转化为UIImage对象,因为这个方法是直接返回二进制数据,所以当加载大图、高清图时使用这个方法可以避免内存暴涨问题;

2.使用PHAsset上传视频遇到的问题

上传大文件一般都是通过文件路径进行上传,但是目前阶段是无法通过PHAsset获取到的文件路径进行上传资源的,所以需要将视频资源导出到指定路径进行上传,使用过两种方法进行导出:

1)、使用requestExportSessionForVideo来导出资源,但是后面发现出了点问题:每次导出的视频都不一样,所生成的MD5都是不一样的,导致验证出了问题,视频的metadata数据应该是导出时被修改过,通过log发现导出后的视频metadata少了部分数据,虽然creationTime没有缺失,但是后台接收到视频后发现creationTime还是错误的

- (void)resetVideoUrlWithAsset:(PHAsset *)videoAsset andResult:(void (^)(NSString *path,NSString *fileName))result andFailed:(void(^)(NSString *error))failure{
    PHVideoRequestOptions *options = [[PHVideoRequestOptions alloc] init];
    options.version = PHImageRequestOptionsVersionCurrent;
    options.deliveryMode = PHVideoRequestOptionsDeliveryModeAutomatic;
    PHImageManager *manager = [PHImageManager defaultManager];
    
    NSString *fileName = [videoAsset valueForKeyPath:@"filename"];
    if (fileName == nil) fileName = @"未命名.mp4";
    NSString *savePath = [[LocolAlbumHelper shareInstance].docPath stringByAppendingPathComponent:fileName];
    
    if ([[NSFileManager defaultManager]fileExistsAtPath:savePath]) {//如果路径有文件,将导致导出失败
        [[NSFileManager defaultManager]removeItemAtPath:savePath error:nil];
    }
    
    [manager requestExportSessionForVideo:videoAsset options:options exportPreset:AVAssetExportPresetHighestQuality resultHandler:^(AVAssetExportSession * _Nullable exportSession, NSDictionary * _Nullable info){
        
        exportSession.outputURL = [NSURL fileURLWithPath:savePath];
        exportSession.shouldOptimizeForNetworkUse = NO;
        exportSession.outputFileType = AVFileTypeMPEG4;
                
        [exportSession exportAsynchronouslyWithCompletionHandler:^{
            AVAssetExportSessionStatus status = [exportSession status];
            switch (status) {
                case AVAssetExportSessionStatusCompleted:
                {
                    CBLog(@"保存成功");
                    if (result) {
                        dispatch_async(dispatch_get_main_queue(), ^{
                            result(savePath,[savePath lastPathComponent]);
                        });
                    }
                    break;
                }
                default:
                    if (failure) {
                        CBLog(@"%ld",(long)status);
                        [[NSFileManager defaultManager]removeItemAtPath:savePath error:nil];
                        dispatch_async(dispatch_get_main_queue(), ^{
                            failure([NSString stringWithFormat:@"%ld",(long)status]);
                        });
                    }
                    break;
            }
        }];
    }];
}

2)、使用requestAVAssetForVideo获取到AVURLAsset后复制NSData到指定路径

- (void)resetVideoUrlWithAsset:(PHAsset *)videoAsset andResult:(void (^)(NSString *path,NSString *fileName))result andFailed:(void(^)(NSString *error))failure{

    NSString *fileName = [videoAsset valueForKeyPath:@"filename"];
    if (fileName == nil) fileName = @"未命名.mp4";
    NSString *savePath = [[LocolAlbumHelper shareInstance].docPath stringByAppendingPathComponent:fileName];
    
    if ([[NSFileManager defaultManager]fileExistsAtPath:savePath]) {//如果路径有文件,将导致导出失败
        [[NSFileManager defaultManager]removeItemAtPath:savePath error:nil];
    }
    
    PHVideoRequestOptions *options = [PHVideoRequestOptions new];
    options.version = PHVideoRequestOptionsVersionOriginal;

    [[PHImageManager defaultManager] requestAVAssetForVideo:videoAsset options:options resultHandler:^(AVAsset * _Nullable asset, AVAudioMix * _Nullable audioMix, NSDictionary * _Nullable info) {
        
        NSError *error;
        AVURLAsset *avurlasset = (AVURLAsset*)asset;
        NSURL *fileURL = [NSURL fileURLWithPath:savePath];
        
        if ([[NSFileManager defaultManager] copyItemAtURL:avurlasset.URL toURL:fileURL error:&error]) {
            CBLog(@"保存成功");
            dispatch_async(dispatch_get_main_queue(), ^{
                if (result) {
                    result(savePath,[savePath lastPathComponent]);
                }
            });
        }else{
            CBLog(@"error=%@",error);
            [[NSFileManager defaultManager]removeItemAtPath:savePath error:nil];
            dispatch_async(dispatch_get_main_queue(), ^{
                failure(error.description);
            });
        }
    }];
}

3.获取视频data的Metadata:

//PHAsset获取Metadata
[[PHImageManager defaultManager]requestAVAssetForVideo:asset options:nil resultHandler:^(AVAsset * _Nullable asset, AVAudioMix * _Nullable audioMix, NSDictionary * _Nullable info) {
    NSString *formatstKey = @"availableMetadataFormats";
    [asset loadValuesAsynchronouslyForKeys:@[formatstKey] completionHandler:^{
        AVKeyValueStatus status = [asset statusOfValueForKey:formatstKey error:nil];
        if (status == AVKeyValueStatusLoaded) {
            for (AVMetadataFormat format in asset.availableMetadataFormats) {
                NSArray *metadata = [asset metadataForFormat:format];
                for (AVMetadataItem *item in metadata) {
                    CBLog(@"%@=%@",item.commonKey,item.value);
                }
            }
        }
    }];
}];

//文件路径获取Metadata 
AVAsset *avasset = [AVAsset assetWithURL:[NSURL fileURLWithPath:path]];
NSString *formatstKey = @"availableMetadataFormats";
[avasset loadValuesAsynchronouslyForKeys:@[formatstKey] completionHandler:^{
    AVKeyValueStatus status = [avasset statusOfValueForKey:formatstKey error:nil];
    if (status == AVKeyValueStatusLoaded) {
        for (AVMetadataFormat format in avasset.availableMetadataFormats) {
            NSArray *metadata = [avasset metadataForFormat:format];
            for (AVMetadataItem *item in metadata) {
                CBLog(@"%@=%@",item.commonKey,item.value);
            }
        }
    }
}];

你可能感兴趣的:(Photos框架使用时发现的问题)