2016-07-03 1 views
0

Idk, почему мое изображение занимает больше места в кеш-памяти, чем исходный размер. Я использую библиотеку alamofireImage для этой цели, и мое приложение предназначено для tvOS. Вот мой код.Изображение занимает больше места в кеше, чем его первоначальный размер в tvos

let photoCache = AutoPurgingImageCache(
     memoryCapacity: 100 * 1024 * 1024, 
     preferredMemoryUsageAfterPurge: 60 * 1024 * 1024 
    ) 


Alamofire.request(.GET, request, headers: headers) 
      .responseJSON { response in 

       if let JSON = response.result.value { 
        self.imagesArray = JSON["results"] as! NSMutableArray 
        for result in self.imagesArray{ 

         self.getNetworkImage(result["url"] as! String, completion: { (UIImage) in 

         })}}} 



func getNetworkImage(urlString: String, completion: (UIImage -> Void)) -> (Request) { 
     return Alamofire.request(.GET, urlString, headers: headers).responseImage { (response) -> Void in 
      guard let image = response.result.value else { return } 
      completion(image) 
      if response.response?.statusCode == 200{ 
       self.cacheImage(image, urlString: urlString) 
       self.cachedImagesOnly.addObject(urlString) 
      } 
      if self.counter == 4{ 
       self.activityIndicatorView.stopAnimating() 
       self.activityIndicatorView.hidden = true 

       var downloadedImage = UIImage() 
       let dicr = self.cachedImagesOnly.firstObject 
       let urlStringFetch = dicr!["url"] as! String 
       print("Fetching url: \(urlStringFetch)") 

       downloadedImage = self.cachedImage(urlStringFetch)! 
       print("Size of image from cache: \(downloadedImage.size)") 
       self.ssImage.image = downloadedImage 

       }) 

      } 

     } 
    } 

func cacheImage(image: Image, urlString: String) { 

     print("Total Cache memory size: \(self.photoCache.memoryCapacity)") 
     self.counter += 1 
     let jpgImageData = UIImageJPEGRepresentation(image, 1.0) 
     print("Image size before cache : \(jpgImageData?.length)") 
     self.cachedImagesOnly.addObject(urlString) 
     let URLRequest = NSURLRequest(URL: NSURL(string: "\(urlString)")!) 
     self.photoCache.addImage(UIImage(data: jpgImageData!)!, forRequest: URLRequest) 
     print("Cache memory usage after image cache: \(self.photoCache.memoryUsage)") 

    } 

Результаты Лог:

Total Cache memory size: 104857600 
Image size: (1752.0, 1896.0) and string as identifier: http://image.com/9493.jpg 
Image size before cache : Optional(1738247) 
Cache memory usage after image cache: 13287168 
Total Cache memory size: 104857600 
Image size: (2875.0, 3872.0) and string as identifier: http://image.com/5025.jpg 
Image size before cache : Optional(7049508) 
Cache memory usage after image cache: 57815168 
Total Cache memory size: 104857600 
Image size: (2394.0, 3866.0) and string as identifier: http://image.com/169215.jpg 
Image size before cache : Optional(6049349) 
Cache memory usage after image cache: 94835984 
Total Cache memory size: 104857600 
Image size: (3811.0, 3049.0) and string as identifier: http://image.com/786.jpg 
Image size before cache : Optional(2848557) 
Cache memory usage after image cache: 46478956 

Итак, я прочитал на GitHub они используют FIFO, когда кэш-память заполнена, поэтому за исключением только удаление первого объекта удаляет два или три, как в расчете. Кроме того, просто рассмотрим первый результат журнала, размер изображения которого составляет 1738247 и IDK, что надбавка к нему добавляет к нему, что после кеша размер использования становится 13287168, что почти в 13 раз более странно. Если бы кто-нибудь прошел через эту проблему или мог идентифицировать мою ошибку, был бы высоко оценен. Заранее спасибо.

+0

Разве они не распакованы в кеше? – Feldur

+0

Nop, я попытался в браузере, размер изображения идеально подходит для обоих. поэтому есть проблема в кеше. –

+1

кажется, что вы сравниваете яблоки и апельсины. Размер представления JPEG и объем памяти, используемый объектом 'UIImage' в кеше, - это две совершенно разные вещи. – Rob

ответ

4

Это немного сложнее, потому что есть много движущихся частей здесь:

  • Во-первых, когда вы получаете изображение с веб-сервиса есть оригинальный достояние, NSData. В вашем фрагменте кода я не думаю, что вы когда-либо видели этот оригинальный актив, потому что вы позволяете Alamofire конвертировать его в UIImage (см. Следующий пункт), прежде чем он будет доставлен вам. Но если вы смотрите это в веб-браузере (или на каком-то инструменте, таком как Charles или WireShark), это размер исходного актива.

  • Затем вы конвертируете это в UIImage, которое, если исходный актив был сжат, может оставаться сжатым до тех пор, пока вы его сначала не используете в UIImageView или тому подобное.

    Как только вы используете этот UIImage, он несжатый, обычно занимает гораздо больше памяти, обычно четыре байта на пиксель (один байт для красного, зеленого, синего и альфа-каналов соответственно, хотя есть и другие форматы) ,

  • Когда вы позже позвоните UIImageJPEGRepresentation, вы теперь строите новый NSData от UIImage. Люди часто ошибочно полагают, что это то же самое, что и исходный актив, но это не так. Если вы используете качество сжатия 1.0, это часто намного больше, чем исходный актив (хотя, вероятно, он меньше, чем несжатый UIImage.) И если вы используете более низкое качество сжатия, размер часто более разумный, но вы вводите некоторые артефакты JPEG из-за его сжатие с потерями. (Сжатие PNG сжатие без потерь, хотя, как правило, в результате активы больше.)

Итак, короче говоря, что вы сравниваете NSData представления (в частности, в формате JPEG с compressionQuality 1) на сумму память занимает UIImage, который кэшируется, и я не ожидал бы соответствия этих чисел. Это разные вещи.

+0

Очень хорошо объяснил @Rob, но у меня есть один вопрос. Если вам нужно решить такую ​​проблему, например, если у вас около 15 изображений, и вы должны кэшировать их в пределах ограничения памяти, что бы вы сделали для этого? –

+0

Во-первых, во многих случаях вам вообще не нужно возиться с кешами, и вы можете наслаждаться кэшированием, предоставляемым «NSURLCache» (который «NSURLSession» автоматически использует за кулисами). К сожалению, кэширование 'NSURLSession' несколько плохо документировано (их странные правила о том, что нет элемента, превышающего 5% от всего кеша) и зависят от заголовков, установленных вашим веб-сервисом. – Rob

+2

В тех случаях, когда мне приходилось реализовывать свой собственный кеш, я (а) кэшировал исходный актив, а не 'UIImage', чтобы избежать несжатых изображений, кэшированных; (b) писать код кэширования, который кэшируется в память с помощью «NSCache» (который я настроил для наблюдения за «UIApplicationDidReceiveMemoryWarningNotification», чтобы очистить себя от давления памяти) и постоянному хранению в «NSSearchPathDirectory.CachesDirectory», в основном, сначала стараясь «NSCache», и вернуться в постоянное хранилище, если «NSCache» не удалось. – Rob

Смежные вопросы