2017-08-29 79 views
0

我在收集視圖中出現非常波濤洶涌的滾動。只有10個電池。這是因爲我檢索圖像的方法是取URL並將其轉爲UIImage數據。UICollectionView快速3 laggy滾動UIImage

圖像變量只是一個圖像URL數組。

public func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { 
    return images.count 
    } 

    public func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { 
    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "mediaCells", for: indexPath) as! MediaCell 
    let url = URL(string: images[indexPath.row] as! String) 
    let data = try? Data(contentsOf: url!) 
    cell.mediaImage.image = UIImage(data: data!) 
    return cell 
    } 

我找到的解決方案是首先爲所有圖像執行此操作。這種方法的問題在於,在我們顯示collectionView之前,它必須等待所有圖像下載數據並追加到數組。在我們可以渲染集合之前,這可能需要幾秒鐘10-15秒。太慢了!

override func viewDidLoad() { 
    super.viewDidLoad() 
    Alamofire.request(URL(string: "myURL")!, 
     method: .get) 
     .responseJSON(completionHandler: {(response) -> Void in 
      if let value = response.result.value{ 
       let json = JSON(value).arrayValue 
       for item in json{ 
        let url = URL(string: item["image"].string!) 
        let data = try? Data(contentsOf: url!) 
        self.images.append(data) 
       } 
       self.collectionView.reloadData() 
     } 
    }) 
    } 
+2

您正在同步下載圖像,請嘗試異步。很少有第三方庫可以輕鬆實現。 – chengsam

+0

謝謝。我遵循你的建議,並使其運行良好。 –

回答

0

有些人會喊使用全局變量,但是這是我以前所做的一切:

聲明的UIImage的全局數組

var images: [UIImage] = [] 

下載圖像後,將其附加到該陣列

for item in json{ 
     let url = URL(string: item["image"].string!) 
     let data = try? Data(contentsOf: url!) 
     let image = UIImage(data: data!) 
     images.append(image) 
     NotificationCenter.default.post(Notification.Name(rawValue: "gotImage"), nil) 
} 

按照通知中的VC

override function viewDidLoad() { 
    NotificationCenter.default.addObserver(self, selector: #selector(collectionView.reloadData()), name: NSNotification.Name(rawValue: "gotImage"), object: nil) 
    super.viewDidLoad() 
} 

不分配一個形象,如果沒有你牢房的CollectionView

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { 
    ..... 
    if let image = images[indexPath].row { 
      cell.mediaImage.image = image 
    } 
    .... 
} 

PS:如果所有的下載並且加載操作發生在同一個VC中,只需在VC類中聲明images即可。

0

好像你需要基於可見的單元格在收藏視圖中延遲加載圖像。我已經實現了像這樣的相同方法。你需要

1)首先步驟來創建一個命名爲PendingOperations.swift

class PendingOperations { 
lazy var downloadsInProgress = [IndexPath: Operation]() 
lazy var downloadQueue: OperationQueue = { 
var queue = OperationQueue() 
queue.name = "downloadQueue" 
queue.maxConcurrentOperationCount = 1 
return queue 
}() 
} 

2)秒步驟創建一個命名爲ImageDownloader類,你可以讓你的網絡電話下載類圖片。

class ImageDownloader: Operation { 
let imageId: String 
init(imageId: String) { 
    self.imageId = imageId 
} 
override func main() { 
    if self.isCancelled { 
    return 
    } 
Alamofire.request(URL(string: "myURL")!, 
     method: .get) 
     .responseJSON(completionHandler: {(response) -> Void in 
      if let value = response.result.value{ 
       let json = JSON(value).arrayValue 
       for item in json{ 
        let url = URL(string: item["image"].string!) 
        self.image = try? Data(contentsOf: url!) 
}) 
if self.isCancelled { 
    return 
    } 
    } 
} 

3)第三步器裏面的viewController一些方法基礎上,可見細胞操縱的操作。

func startDownload(_ image: imageId, indexPath: IndexPath) { 
if let _ = pendingOperations.downloadsInProgress[indexPath] { 
    return 
} 
let downloader = ImageDownloader(image: imageId) 
downloader.completionBlock = { 
    if downloader.isCancelled { 
    return 
    } 
} 
pendingOperations.downloadsInProgress.removeValue(forKey: indexPath) 
pendingOperations.downloadsInProgress[indexPath] = downloader 
pendingOperations.downloadQueue.addOperation(downloader) 
} 
} 

func suspendAllOperation() { 
pendingOperations.downloadQueue.isSuspended = true 
} 

func resumeAllOperation() { 
    pendingOperations.downloadQueue.isSuspended = false 
} 

func loadImages() { 
let pathArray = collectionView.indexPathsForVisibleItems 
let allPendingOperations = 
Set(Array(pendingOperations.downloadsInProgress.keys)) 
let visiblePath = Set(pathArray!) 
var cancelOperation = allPendingOperations 
cancelOperation.subtract(visiblePath) 
var startOperation = visiblePath 
startOperation.subtract(allPendingOperations) 
for indexpath in cancelOperation { 
    if let pendingDownload = 
pendingOperations.downloadsInProgress[indexpath] { 
pendingDownload.cancel() 
} 
pendingOperations.downloadsInProgress.removeValue(forKey: indexpath) 
} 
for indexpath in startOperation { 
    let indexPath = indexpath 
    startDownload(imageId, indexPath: indexPath) 
} 
} 

4)第四步驟,執行滾動視圖委託方法。

func scrollViewWillBeginDragging(_ scrollView: UIScrollView) { 
     suspendAllOperation() 
    } 

func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) { 
    loadImages() 
    resumeAllOperation() 
} 

func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) { 
    if !decelerate { 
     loadImages() 
     resumeAllOperation() 
    } 
} 

func clearImageDownloaderOperations() { 
    if pendingOperations.downloadsInProgress.count > 0 { 
     pendingOperations.downloadsInProgress.removeAll() 
     pendingOperations.downloadQueue.cancelAllOperations() 
    } 
}