2014-09-24 2 views
37

Я конвертирую наше приложение, чтобы использовать Рамки фотографий iOS8, структура ALAsset явно является гражданином второго класса под iOS8.NSURL от PHAsset

У меня возникла проблема в том, что наша архитектура действительно хочет, чтобы NSURL представлял местоположение носителя на «диске». Мы используем его для загрузки медиа на наши серверы для дальнейшей обработки.

Это было легко с ALAsset:

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

Но я просто не видел эту способность в PHAsset. Я предполагаю, что я могу назвать:

imageManager.requestImageDataForAsset 

, а затем записать его в виде временного места в файловой системе, но это кажется ужасно тяжеловесным и расточительно, не говоря уже о потенциально медленно.

Есть ли способ получить это, или я собираюсь иметь рефакторинг большего количества моего приложения, чтобы использовать только NSURL для iOS7 и какой-либо другой метод для iOS8?

+0

Глядя на мой код немного больше единственная причина, почему я использую URL, чтобы кормить его AVAssetExportSession и/или AVAssetImageGenerator, поэтому, я думаю, я просто заменю эти вызовы. Опять же, как только я подаю это тем, мне все еще нужен NSURL, чтобы перейти к нашему загрузчику, поэтому я готов поспорить, что проблема все еще существует. –

+1

Из вашего комментария здесь, кажется, вы уже поняли это для себя, но для других, чтобы увидеть это здесь: Если вам нужно только использовать URL-адрес для более старых методов (например, AVAssetExportSession), вы, вероятно, можете использовать более новые версии из них, которые соответствуют PHASset, а не AVASset (AVURLAsset). Например: requestExportSessionForVideo и requestPlayerItemForVideo из PHImageManager.defaultManager() –

ответ

23

Если вы используете [imageManagerrequestAVAssetForVideo ...], он вернет AVAsset. Этот AVAsset на самом деле является AVURLAsset, поэтому, если вы его бросите, вы можете получить доступ к нему - url.

Я не уверен, что вы можете создать новый актив из этого, но он дает вам место.

+0

вы снова! : -) Я забыл об этом вопросе. Я пошел по другому пути, посмотрю на другой вопрос, но это тоже верно. Кстати, вы не работали для Kodak в 80-х годах, не так ли? Знал jlw назад тогда ... –

+4

может быть, тупой вопрос, но делает ли это работу как для изображений, так и для видео? – gdbj

+1

Это не работает для slo-mo видео, которое вернет AVCompostion, чей суперкласс AVAsset. AVAsset имеет подклассы, такие как AVURLAsset и AVAsset. – rishu1992

9

Если у вас есть PHAsset, вы можете получить URL для указанного актива, как это:

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

Используйте новый localIdentifier свойство PHObject. (PHASset наследует от этого).

Он предоставляет аналогичные функциональные возможности к URL ALAsset, а именно, что вы можете загрузить активы путем вызова метода

+[PHAsset fetchAssetsWithLocalIdentifiers:identifiers options:options] 
17

SWIFT версии 2.0 Эта функция возвращает NSURL из PHAsset (как изображения и видео)

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) 
      } 
     }) 
    } 

} 
+0

Как я могу прочитать содержимое пути? Похоже, что когда я пытаюсь получить с NSData (contentsOfFile: «...»), это не собирается получать. Есть ли способ прочитать этот файл из Path как «file: ///var/mobile/Media/PhotoData/PhotoCloudSharingData/211607360/28D50A9E-57E3-4280-B75D-7DC228A19147/100CLOUD/IMG_1170.JPG« –

+0

var path: String = pathURL.path() данные var: NSData = NSFileManager.defaultManager(). contentsAtPath (path) –

+6

Кажется, что у меня нет доступа или что-то (доступ к библиотеке фотографий предоставляется). Когда я пытаюсь NSFileManager.defaultManager(). FileExistsAtPath() возвращает false, поэтому я также не могу получить содержимое файла. Но файл определенно существует. –

3

См. Этот ответ here.

И этот here.

По моему опыту вам нужно сначала экспортировать актив на диск, чтобы получить полностью доступный/надежный URL-адрес.

В ответах, приведенных выше, описывается, как это сделать.

5

Все вышеупомянутые решения не будут работать для замедленного просмотра видео. Решение, которое я нашел, обрабатывает все типы видео активов заключается в следующем:

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 
     } 
    } 
} 
0

Я был похож проблема с видеофайлами, что работает для меня было:

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

Где актив PHAsset.

1

В speking ВГД от PHAsset, я когда-то подготовил UTIL FUNC на Swift 2 (хотя только для воспроизведения видео с PHAsset). Совместное использование этого ответа может помочь кому-то.

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

Пожалуйста, проверьте это Answer

1

Просто хотят, чтобы разместить скрытый драгоценный камень из комментария от @jlw

@ rishu1992 Для замедленного-мо видео, захватить AVComposition в AVCompositionTrack (из MEDIATYPE AVMediaTypeVideo), возьмите свой первый сегмент (типа AVCompositionTrackSegment), а затем получите доступ к свойству sourceURL . - JLW 25 августа '15 в 11:52

1

Вот удобная категория 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 
Смежные вопросы