2017-07-26 235 views
5

我想象的是一種非常常見的情況,我期望能夠輕鬆解決這個問題 - 帶有UICollectionView的應用程序,每個單元中的圖像都是從API中獲取的通過http/https在Web服務器上。在UICollectionView和UITableView中優化預加載/預取圖像

我試圖實施iOS 10的prefetching in UICollectionView,以便提前請求可能需要的圖像。

在我看來,有應滿足最優預取各種要求:

  1. 這實際上是立即要求應始終上述推測預取優先圖像取,即使圖像已經在一個隊列被提取。
  2. 當iOS告訴我們一個特定的圖像不再需要被預取時,它應該從預取隊列中移除(並且只有它)。
  3. 如果請求圖像,應始終發送圖像,除非/取消所有/請求(如果在多個單元格或多個視圖控制器中使用一個圖像,則容易出錯)。
  4. 如果調用了didEndDisplaying,則應該中止優先級提取(但是,如果請求預取並且未取消,應該可能將該映像留在隊列中的優先級較低)。
  5. 簡單地涉及圖像加載的各種常見要求 - 例如。不要使用預取請求淹沒底層系統,最終會導致帶寬和服務器插槽遠離立即需要的映像。

我看像SDWebImageKingfisher現有的各種庫,並感到驚訝的是,似乎沒有要任何方式與任何庫輕鬆滿足上述要求。例如,SDWebImage不符合第二個要求 - 您只能使用cancel all prefetching,或者您必須爲每個圖像創建一個預先獲取器(這意味着各種其他SDWebImage功能,例如限制併發請求的數量,提取的圖像 - 即需求5 - 不再有效。)

這真的是一個難題嗎?我錯過了一些明顯的解決方案?我是否超越了要求?

回答

0

看起來你需要實現自己的優先級,如果從prefetchItemsAt索引路徑傳遞的最新索引路徑是不夠的。

要求1,2,3使用優先級隊列(Sorted Heap)完成。要求4取決於您的實施優先級隊列。 5是相當寬泛和模糊的,只是限制調用您的方法獲取的次數。 Priority Queue採用泛型類型,因此您可以將它與具有您希望獲取的項目的屬性的對象/類一起使用,下面我簡單地使用IndexPath.row。

創建一個優先級隊列,用作數據源和緩存之間的中介。

然後通過查看/取出優先級隊列並存儲在Kingfisher中,設置要從DataSource中獲取的數據。 您的數據源 - >的PriorityQueue - >翠鳥 - >細胞

func collectionView(_ collectionView: UICollectionView, prefetchItemsAt indexPaths: [IndexPath]) { 
    ... 
    for indexPath in IndexPaths { 
     //Add the indexPath to the top of the priority queue 
     //highest priority is determined by the sort function you used when initializing the priority queue. 
     priorityQueue?.enqueue(indexpath.row) 
    } 

    //Call your method for getting the properties 
    self.fetchObjectsByPriority() 
} 


func fetchObjectsByPriority() { 
     if let count = priorityQueue?.count { 
     for _ in 0...count { 

      //get the index 
      var index = self.priorityQueue?.dequeue() 
      //Alternatively .peek() with out dequeuing item 
      //get image data and store 
      dataSource[index].image = ... 

     } 
    } 
} 

確保您初始化優先級隊列帶有排序功能。

您可以從here獲得預建優先級隊列,您還需要heap來創建優先級隊列。

更多priority Queuesheap sorting

沒有問題的代碼是很難提供有效的解決方案。我希望這有助於,歡呼和祝你好運!