如何使用 PHAssetResource RequestOptions progressHandler/PHAssetResourceProgressHandler
How to use PHAssetResourceRequestOptions progressHandler/PHAssetResourceProgressHandler
我正在尝试 retrieve/download Live Photo 的 video/frames。
至于 API 文档,有一种可能的情况是实时照片将存储在 iCloud 中。为了也检索它们,您需要声明
let options = PHAssetResourceRequestOptions()
options.networkAccessAllowed = true
我正在尝试在下载实时照片时创建进度条。根据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)
}
})
是的,不幸的是,iCloud 下载 + PHAssetResourceManager 存在 Apple 错误。无论资产类型如何,我都会收到以下错误:
Error: Missing resource download context
改为使用 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();
}
}];
}
}];
}
}
@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);
}
}
我正在尝试 retrieve/download Live Photo 的 video/frames。 至于 API 文档,有一种可能的情况是实时照片将存储在 iCloud 中。为了也检索它们,您需要声明
let options = PHAssetResourceRequestOptions()
options.networkAccessAllowed = true
我正在尝试在下载实时照片时创建进度条。根据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)
}
})
是的,不幸的是,iCloud 下载 + PHAssetResourceManager 存在 Apple 错误。无论资产类型如何,我都会收到以下错误:
Error: Missing resource download context
改为使用 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();
}
}];
}
}];
}
}
@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);
}
}