【问题标题】:How to use PHAssetResourceRequestOptions progressHandler/PHAssetResourceProgressHandler如何使用 PHAssetResourceRequestOptions progressHandler/PHAssetResourceProgressHandler
【发布时间】:2016-05-16 10:49:58
【问题描述】:

我正在尝试检索/下载 Live Photo 的视频/帧。 至于 API 文档,Live Photos 可能会存储在 iCloud 中。为了同时检索它们,您需要声明

let options = PHAssetResourceRequestOptions()
        options.networkAccessAllowed = true  

我正在尝试在下载 Live Photo 时创建进度条。根据 API,您需要声明此属性:

public var progressHandler: PHAssetResourceProgressHandler?

progress    
A floating-point value indicating the progress of the download. 
A value of 0.0 indicates that the download has just started,
and a value of 1.0 indicates the download is complete. 

我还没有找到正确的方法来检索这些。有什么建议吗?

完整代码:

 let assestResource = PHAssetResource.assetResourcesForAsset(asset)
 let options = PHAssetResourceRequestOptions()
 options.networkAccessAllowed = true
for assetRes in assestResource {
            print(assetRes.type.rawValue)
            if (assetRes.type == .PairedVideo) {
                print("imageTaken")
                manager.writeDataForAssetResource(assetRes, toFile: documentsURL,    options: options, completionHandler: { (error) -> Void in
                    if error == nil
                    {

                    }
                    else
                    {
                        print(error)
                    }
                })

【问题讨论】:

    标签: ios objective-c swift progress phasset


    【解决方案1】:

    是的,不幸的是,iCloud 下载 + PHAssetResourceManager 存在 Apple 错误。无论资产类型如何,我都会收到以下错误:

    错误:缺少资源下载上下文

    改为使用 PHImageManager。您需要对每种类型的 PHAsset 有一个唯一的请求:

    - (void)downloadAsset:(PHAsset *)asset toURL:(NSURL *)url completion:(void (^)(void))completion
    {
        if (asset.mediaType == PHAssetMediaTypeImage && (asset.mediaSubtypes & PHAssetMediaSubtypePhotoLive))
        {
            PHLivePhotoRequestOptions *options = [PHLivePhotoRequestOptions new];
            options.networkAccessAllowed = YES;
            [[PHImageManager defaultManager] requestLivePhotoForAsset:asset targetSize:CGSizeZero contentMode:PHImageContentModeAspectFill options:options resultHandler:^(PHLivePhoto * _Nullable livePhoto, NSDictionary * _Nullable info) {
                if ([info objectForKey:PHImageErrorKey] == nil)
                {
                    NSData *livePhotoData = [NSKeyedArchiver archivedDataWithRootObject:livePhoto];
                    if ([[NSFileManager defaultManager] createFileAtPath:url.path contents:livePhotoData attributes:nil])
                    {
                        NSLog(@"downloaded live photo:%@", url.path);
                        completion();
                    }
                }
            }];
        }
        else if (asset.mediaType == PHAssetMediaTypeImage)
        {
            PHImageRequestOptions *options = [PHImageRequestOptions new];
            options.networkAccessAllowed = YES;
            [[PHImageManager defaultManager] requestImageDataForAsset:asset options:options resultHandler:^(NSData * _Nullable imageData, NSString * _Nullable dataUTI, UIImageOrientation orientation, NSDictionary * _Nullable info) {
                if ([info objectForKey:PHImageErrorKey] == nil
                    && [[NSFileManager defaultManager] createFileAtPath:url.path contents:imageData attributes:nil])
                {
                    NSLog(@"downloaded photo:%@", url.path);
                    completion();
                }
            }];
        }
        else if (asset.mediaType == PHAssetMediaTypeVideo)
        {
            PHVideoRequestOptions *options = [PHVideoRequestOptions new];
            options.networkAccessAllowed = YES;
            [[PHImageManager defaultManager] requestExportSessionForVideo:asset options:options exportPreset:AVAssetExportPresetHighestQuality resultHandler:^(AVAssetExportSession * _Nullable exportSession, NSDictionary * _Nullable info) {
                if ([info objectForKey:PHImageErrorKey] == nil)
                {
                    exportSession.outputURL = url;
    
                    NSArray<PHAssetResource *> *resources = [PHAssetResource assetResourcesForAsset:asset];
                    for (PHAssetResource *resource in resources)
                    {
                        exportSession.outputFileType = resource.uniformTypeIdentifier;
                        if (exportSession.outputFileType != nil)
                            break;
                    }
    
                    [exportSession exportAsynchronouslyWithCompletionHandler:^{
                        if (exportSession.status == AVAssetExportSessionStatusCompleted)
                        {
                            NSLog(@"downloaded video:%@", url.path);
                            completion();
                        }
                    }];
                }
            }];
        }
    }
    

    【讨论】:

    • 太棒了,谢谢!但是@Photo 部分是否只占用预览帧,对吗?
    • 预览框是什么意思?
    • 取决于您的 options 参数。根据 Apple 文档,对于 PHAssetMediaTypeImage:If the version option is set to PHImageRequestOptionsVersionCurrent, Photos provides rendered image data, including the results of any edits that have been made to the asset content. Otherwise, Photos provides the originally captured image data for the asset.
    • 我遇到了持久化 PHLivePhoto 资产的复杂情况,因为它不保存视频数据,它通过 url 引用视频。因此,无论 iCloud 是否正常工作,我都会将 PHAssetResourceManager 用于实时照片。我希望 PHLivePhoto 能像 UIImage 一样工作,它可以轻松地与 NSData 相互转换。
    • 是的。他们在 PHAssetResourceManager 上有非常好的 API。也很干净。我可以习惯它:)
    【解决方案2】:

    @owjhart:很好的解决方案!!!

    对于那些想要将生活照片作为电影文件抓取的人,我已经采用了一些代码:-)

    - (void)downloadAsset:(PHAsset *)pAsset
               completion:(void (^)(BOOL pSucceeded, NSURL* pURL))pCompletion {
        NSParameterAssert(pCompletion);
    
    
        if ((PHAssetMediaTypeImage == pAsset.mediaType) &&
            (pAsset.mediaSubtypes & PHAssetMediaSubtypePhotoLive)) {
    
            NSArray*            assetResources = [PHAssetResource assetResourcesForAsset:pAsset];
            PHAssetResource*    assetResource = nil;
            for (PHAssetResource* asress in assetResources) {
                if (UTTypeConformsTo((__bridge CFStringRef)asress.uniformTypeIdentifier, kUTTypeMovie)) {
                    assetResource = asress;
                    break;
                }
            }
    
            if (assetResource) {
                __block NSMutableData*      assetData = NSMutableData.new;
                [PHAssetResourceManager.defaultManager requestDataForAssetResource:assetResource
                                                                           options:nil
                                                               dataReceivedHandler:^(NSData * _Nonnull pData) {
                                                                   [assetData appendData:pData];
                                                               }
                                                                 completionHandler:^(NSError * _Nullable pError) {
                                                                     //kUTTypeLivePhoto
                                                                     CFStringRef extension = UTTypeCopyPreferredTagWithClass((__bridge CFStringRef)assetResource.uniformTypeIdentifier, kUTTagClassFilenameExtension);
                                                                     NSString*  filename = [NSString stringWithFormat:@"%@.%@", NSProcessInfo.processInfo.globallyUniqueString, extension];
                                                                     NSURL*     tempURL = [[NSURL fileURLWithPath:NSTemporaryDirectory()
                                                                                                   isDirectory:YES] URLByAppendingPathComponent:filename];
                                                                     if ((!pError) &&
                                                                         (assetData.length) &&
                                                                         ([NSFileManager.defaultManager createFileAtPath:tempURL.path
                                                                                                                contents:assetData
                                                                                                              attributes:nil])) {
                                                                         pCompletion(YES, tempURL);
                                                                     }
                                                                     else {
                                                                         pCompletion(NO, nil);
                                                                     }
                                                                 }];
            }
            else {
                pCompletion(NO, nil);
            }
        }
        else if (PHAssetMediaTypeImage == pAsset.mediaType) {
    
            PHImageRequestOptions*  options = PHImageRequestOptions.new;
            options.networkAccessAllowed = YES;
            [PHImageManager.defaultManager requestImageDataForAsset:pAsset
                                                            options:options
                                                      resultHandler:^(NSData * _Nullable imageData, NSString * _Nullable dataUTI, UIImageOrientation orientation, NSDictionary * _Nullable info) {
    
                CFStringRef extension = UTTypeCopyPreferredTagWithClass((__bridge CFStringRef)dataUTI, kUTTagClassFilenameExtension);
                NSString*   filename = [NSString stringWithFormat:@"%@.%@", NSProcessInfo.processInfo.globallyUniqueString, (__bridge NSString*)extension];
                NSURL*      tempURL = [[NSURL fileURLWithPath:NSTemporaryDirectory()
                                              isDirectory:YES] URLByAppendingPathComponent:filename];
                if ((nil == [info objectForKey:PHImageErrorKey]) &&
                    ([NSFileManager.defaultManager createFileAtPath:tempURL.path 
                                                           contents:imageData
                                                         attributes:nil])) {
                    NSLog(@"downloaded photo:%@", tempURL.path);
                    pCompletion(YES, tempURL);
                }
                else {
                    pCompletion(NO, nil);
                }
            }];
        }
        else if (PHAssetMediaTypeVideo == pAsset.mediaType) {
    
            PHVideoRequestOptions*  options = PHVideoRequestOptions.new;
            options.networkAccessAllowed = YES;
            [PHImageManager.defaultManager requestExportSessionForVideo:pAsset
                                                                options:options
                                                           exportPreset:AVAssetExportPresetHighestQuality
                                                          resultHandler:^(AVAssetExportSession * _Nullable exportSession, NSDictionary * _Nullable info) {
                if (nil == [info objectForKey:PHImageErrorKey]) {
                    NSArray<PHAssetResource*>*  resources = [PHAssetResource assetResourcesForAsset:pAsset];
                    for (PHAssetResource* resource in resources) {
                        exportSession.outputFileType = resource.uniformTypeIdentifier;
                        if (nil != exportSession.outputFileType) {
                            break;
                        }
                    }
                    CFStringRef extension = UTTypeCopyPreferredTagWithClass((__bridge CFStringRef)exportSession.outputFileType, kUTTagClassFilenameExtension);
                    NSString*   filename = [NSString stringWithFormat:@"%@.%@", NSProcessInfo.processInfo.globallyUniqueString, (__bridge NSString*)extension];
                    NSURL*      tempURL = [[NSURL fileURLWithPath:NSTemporaryDirectory()
                                                  isDirectory:YES] URLByAppendingPathComponent:filename];
                    exportSession.outputURL = tempURL;
    
    
                    [exportSession exportAsynchronouslyWithCompletionHandler:^{
                        if (AVAssetExportSessionStatusCompleted == exportSession.status) {
                            NSLog(@"downloaded video:%@", tempURL.path);
                            pCompletion(YES, tempURL);
                        }
                        else {
                            pCompletion(NO, nil);
                        }
                    }];
                }
                else {
                    pCompletion(NO, nil);
                }
            }];
        }
        else {
            pCompletion(NO, nil);
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-07-29
      • 1970-01-01
      • 1970-01-01
      • 2014-08-19
      • 2012-02-29
      • 2019-02-09
      相关资源
      最近更新 更多