2015-09-21 2 views
1

Я пытаюсь извлечь эскиз, а также другую информацию из PHAsset. Ниже приведен упрощенный фрагмент кода.Извлечение эскизов из PHAsset

Для всех изображений, которые я извлечь из камеры ролла сделать:

static func fetchAsset(asset: PHAsset) 
{ 
     if(asset.mediaType == PHAssetMediaType.Image){ 
      let screenScale: CGFloat = UIScreen.mainScreen().scale 
      let imageSize = CGSize(width: 100 * screenScale, height: 100 * screenScale) 

      let options: PHImageRequestOptions = PHImageRequestOptions() 
      options.deliveryMode = PHImageRequestOptionsDeliveryMode.FastFormat 
      options.resizeMode = PHImageRequestOptionsResizeMode.Fast 
      options.synchronous = false 

      PHImageManager.defaultManager().requestImageForAsset(asset, 
       targetSize: imageSize, 
       contentMode: PHImageContentMode.AspectFill, 
       options: options, 
       resultHandler: { (result, info) -> Void in 
        if (result != nil && result!.scale == screenScale) { 

         var newItemImage = MyImage(isLocal:true) 
         if let fname = asset.valueForKey("filename") as? String{ 
          newItemImage.fileName = fname 
         } 
         newItemImage.thumbnail = result 
         asset.requestContentEditingInputWithOptions(PHContentEditingInputRequestOptions()) { (contentEditingInput, info) -> Void in 

          //Get full image 
          let url = contentEditingInput!.fullSizeImageURL 

          newItemImage.url = url 
         } 
         //DO SOMWTHING WITH IMAGE 
        }else 
        { 
         //DO SOMWTHING ELSE 
        } 
      }) 
     } 
    } 

У меня есть две проблемы на данном этапе:

  1. Наиболее важные из них, но я предполагаю, что это следствие. Требуется слишком много энергии обработки и чтения с диска. Он отлично работает в эмуляторе . Но когда я запускаю его на тестовом устройстве (iPhone 5, 4S), у которого есть 300-500 изображений, он зависает в течение минуты или двух, получая все изображения. Я предполагаю, что он читает всю коллекцию один на один, изменяет размер и извлекает всю эту информацию. Есть ли более простой способ? Как это было возможно с ALAsset, я мог просто получить эскиз напрямую, и он быстро летал.
  2. Он делает работу дважды по какой-то причине. Сначала это дает мне то, о чем я просил, маленькие миниатюры ~ 60 * 40 или около того. Как только он дал мне, что через пару секунд он отправляется на другой цикл и начинает извлекать изображения с более высоким разрешением, например 960 * 640 или около того, и здесь происходит замерзание. Я не уверен, почему это происходит, но это так.

Любые данные по этим двум проблемам будут высоко оценены.

ответ

2

Это делает работу дважды по какой-то причине

Потому что это то, что он должен делать. Получение изображений из библиотеки фотографий требует времени, как вы обнаружили. Поэтому поведение по умолчанию заключается в том, что мы предоставляем изображение с низким разрешением как можно быстрее, просто чтобы у вас было что-то отображаемое; мы снова вызываем, возможно, несколько раз, с более качественными версиями изображения. Кроме того, выборка формируется асинхронно. Таким образом, вполне возможно, что вы получите сразу несколько запросов на выборку, что может привести к тому, что ваш код начнет натыкаться на собственные ноги, как вы обнаружили.

Если вам это не нравится, установите параметры выборки synchronous в true - но тогда вы должны сделать весь этот звонок в фоновом режиме! Делая это в очереди серий, вы можете убедиться, что вызовы выполняются отдельно по очереди, и каждое изображение будет доставлено только один раз. Более того, тогда (и только тогда) ваш PHImageRequestOptions.DeliveryModeFastFormat будет соблюден. Не забудьте вернуться к основной теме, прежде чем делать что-либо с изображением, которое вы получаете!

+0

.Hi, спасибо, но есть способ для получения фотографии с низким разрешением и сказать, что это все? Я не могу найти такой вариант в документации. – IvanN

+0

Во-первых, попросите размер меньшего размера. Вы умножаете 100x100 на разрешение экрана; не делайте этого. С другой стороны, вы поставляете PHImageRequestOptions, которые бессмысленны _unless_ ваши параметры выборки являются «синхронными»! Вы уже просите результаты с низким разрешением, но это бессмысленно, пока вы не сделаете то, что я сказал. Поэтому, пожалуйста, просто _try_ делать то, что я сказал, хорошо? – matt

+0

Я не умножаю, если по разрешению экрана я умножаю его по шкале экрана, а если я распечатываю, то выдаст 1.0 или 2.0, поэтому я предполагаю, что это способ сделать изображения подходящими для разных экранов. – IvanN

0

Вы также можете использовать это расширение, которое я написал:

import Photos 

extension PHAsset { 
    var thumbnailImage : UIImage { 
     get { 
      let manager = PHImageManager.default() 
      let option = PHImageRequestOptions() 
      var thumbnail = UIImage() 
      option.isSynchronous = true 
      manager.requestImage(for: self, targetSize: CGSize(width: 300, height: 300), contentMode: .aspectFit, options: option, resultHandler: {(result, info)->Void in 
       thumbnail = result! 
      }) 
      return thumbnail 
     } 
    } 
} 
Смежные вопросы