ios8 alassetslibrary photosframework phasset

ios8 - NSURL de PHAsset



alassetslibrary photosframework (10)

Estoy convirtiendo nuestra aplicación para usar Photos Framework de iOS8, el framework ALAsset es claramente un ciudadano de segunda clase bajo iOS8.

Estoy teniendo un problema es que nuestra arquitectura realmente quiere un NSURL que represente la ubicación de los medios en "disco". Usamos esto para cargar los medios a nuestros servidores para su posterior procesamiento.

Esto fue fácil con ALAsset:

ALAssetRepresentation *rep = [asset defaultRepresentation]; self.originalVideo = rep.url;

Pero no estoy viendo esta habilidad en PHAsset. Creo que puedo llamar:

imageManager.requestImageDataForAsset

y luego escribirlo en un punto temporal en el sistema de archivos, pero parece terriblemente pesado y derrochador, por no hablar de potencialmente lento.

¿Hay alguna forma de obtener esto o tendré que refacturar más mi aplicación para que solo use NSURL para iOS7 y algún otro método para iOS8?


Al expresar la URL de PHAsset , una vez había preparado un programa de utilidad en Swift 2 (aunque solo para reproducir videos de PHAsset ). Compartirlo en esta respuesta, podría ayudar a alguien.

static func playVideo (view:UIViewController, asset:PHAsset)

Por favor revisa esta Answer


Aquí hay una práctica categoría PHAsset:

@implementation PHAsset (Utils) - (NSURL *)fileURL { __block NSURL *url = nil; switch (self.mediaType) { case PHAssetMediaTypeImage: { PHImageRequestOptions *options = [[PHImageRequestOptions alloc] init]; options.synchronous = YES; [PHImageManager.defaultManager requestImageDataForAsset:self options:options resultHandler:^(NSData *imageData, NSString *dataUTI, UIImageOrientation orientation, NSDictionary *info) { url = info[@"PHImageFileURLKey"]; }]; break; } case PHAssetMediaTypeVideo: { dispatch_semaphore_t semaphore = dispatch_semaphore_create(0); [PHImageManager.defaultManager requestAVAssetForVideo:self options:nil resultHandler:^(AVAsset *asset, AVAudioMix *audioMix, NSDictionary *info) { if ([asset isKindOfClass:AVURLAsset.class]) { url = [(AVURLAsset *)asset URL]; } dispatch_semaphore_signal(semaphore); }]; dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER); break; } default: break; } return url; } @end


Si tiene un PHAsset, puede obtener la URL de dicho activo de la siguiente manera:

[asset requestContentEditingInputWithOptions:editOptions completionHandler:^(PHContentEditingInput *contentEditingInput, NSDictionary *info) { NSURL *imageURL = contentEditingInput.fullSizeImageURL; }];


Si usa [ imageManager requestAVAssetForVideo ...], devolverá un AVAsset . Ese AVAsset es realmente un AVURLAsset , por lo que si lo AVURLAsset , puedes acceder a su propiedad url .

No estoy seguro si puede crear un nuevo activo a partir de esto, pero sí le da la ubicación.


Solo quiero publicar la gema oculta de un comentario de @jlw

@ rishu1992 Para videos de cámara lenta, tome AVCompositionTrack de AVComposition (de mediaType AVMediaTypeVideo), tome su primer segmento (de tipo AVCompositionTrackSegment) y luego acceda a su propiedad sourceURL. - jlw 25 de agosto de 15 a 11:52


Tenía un problema similar con los archivos de video, lo que funcionó para mí fue:

NSString* assetID = [asset.localIdentifier substringToIndex:(asset.localIdentifier.length - 7)]; NSURL* videoURL = [NSURL URLWithString:[NSString stringWithFormat:@"assets-library://asset/asset.mov?id=%@&ext=mov", assetID]];

Donde el activo es PHAsset.


Todas las soluciones anteriores no funcionarán para videos de cámara lenta. Una solución que encontré maneja todos los tipos de activos de video es esta:

func createFileURLFromVideoPHAsset(asset: PHAsset, destinationURL: NSURL) { PHCachingImageManager().requestAVAssetForVideo(self, options: nil) { avAsset, _, _ in let exportSession = AVAssetExportSession(asset: avAsset!, presetName: AVAssetExportPresetHighestQuality)! exportSession.outputFileType = AVFileTypeMPEG4 exportSession.outputURL = destinationURL exportSession.exportAsynchronouslyWithCompletionHandler { guard exportSession.error == nil else { log.error("Error exporting video asset: /(exportSession.error)") return } // It worked! You can find your file at: destinationURL } } }


Use la nueva propiedad localIdentifier de PHObject. (PHAs hereda de esto).

Proporciona una funcionalidad similar a una URL ALAsset, es decir, que puede cargar activos llamando al método

+[PHAsset fetchAssetsWithLocalIdentifiers:identifiers options:options]


Vea esta respuesta here .

Y este here .

Según mi experiencia, primero deberá exportar el activo a un disco para obtener una URL confiable y totalmente accesible.

Las respuestas vinculadas a arriba describen cómo hacer esto.


Versión de SWIFT 2.0 Esta función devuelve NSURL de PHAsset (tanto de imagen como de video)

func getAssetUrl(mPhasset : PHAsset, completionHandler : ((responseURL : NSURL?) -> Void)){ if mPhasset.mediaType == .Image { let options: PHContentEditingInputRequestOptions = PHContentEditingInputRequestOptions() options.canHandleAdjustmentData = {(adjustmeta: PHAdjustmentData) -> Bool in return true } mPhasset.requestContentEditingInputWithOptions(options, completionHandler: {(contentEditingInput: PHContentEditingInput?, info: [NSObject : AnyObject]) -> Void in completionHandler(responseURL : contentEditingInput!.fullSizeImageURL) }) } else if mPhasset.mediaType == .Video { let options: PHVideoRequestOptions = PHVideoRequestOptions() options.version = .Original PHImageManager.defaultManager().requestAVAssetForVideo(mPhasset, options: options, resultHandler: {(asset: AVAsset?, audioMix: AVAudioMix?, info: [NSObject : AnyObject]?) -> Void in if let urlAsset = asset as? AVURLAsset { let localVideoUrl : NSURL = urlAsset.URL completionHandler(responseURL : localVideoUrl) } else { completionHandler(responseURL : nil) } }) } }