某些上下文:我有一個UICollectionView
,它將顯示大約一千個微小圖像,但其中只有大約100個可同時顯示。iOS:保持用戶界面在圖像加載到單獨線程時響應
我需要在單獨的線程中從磁盤加載此圖像,以便UI不會被阻止,並且用戶可以在圖像仍然出現時與應用程序進行交互。
要做到這一點,我在斯威夫特實施rob mayoff's answer到Proper way to deal with cell reuse with background threads?如下,其中PotoCell
是UICollectionViewCell
一個子類:
var myQueue = dispatch_queue_create("com.dignityValley.Autoescuela3.photoQueue", DISPATCH_QUEUE_SERIAL)
var indexPathsNeedingImages = NSMutableSet()
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCellWithReuseIdentifier(reuseIdentifier, forIndexPath: indexPath) as! PhotoCell
cell.imageView.image = nil
indexPathsNeedingImages.addObject(indexPath)
dispatch_async(myQueue) { self.bg_loadOneImage() }
return cell
}
func bg_loadOneImage() {
var indexPath: NSIndexPath?
dispatch_sync(dispatch_get_main_queue()) {
indexPath = self.indexPathsNeedingImages.anyObject() as? NSIndexPath
if let indexPath = indexPath {
self.indexPathsNeedingImages.removeObject(indexPath)
}
}
if let indexPath = indexPath {
bg_loadImageForRowAtIndexPath(indexPath)
}
}
func bg_loadImageForRowAtIndexPath(indexPath: NSIndexPath) {
if let cell = self.cellForItemAtIndexPath(indexPath) as? PhotoCell {
if let image = self.photoForIndexPath(indexPath) {
dispatch_async(dispatch_get_main_queue()) {
cell.imageView.image = image
self.indexPathsNeedingImages.removeObject(indexPath)
}
}
}
}
func collectionView(collectionView: UICollectionView, didEndDisplayingCell cell: UICollectionViewCell, forItemAtIndexPath indexPath: NSIndexPath) {
indexPathsNeedingImages.removeObject(indexPath)
}
但是,我沒有得到滿意的結果:當我滾動時,當圖像在後臺加載時,UI會凍結幾分之一秒。滾動不夠流暢。此外,在加載前100張圖像時,我無法滾動顯示最後一張圖像。在執行多線程之後,UI仍然被阻塞。這previosly我使用的是自定義的串行隊列
var myQueue = dispatch_get_global_queue(QOS_CLASS_BACKGROUND, 0)
注:
出人意料的是,我可以通過修改我的隊列,以達到理想的平整度。
在這個改變後,用戶界面完全響應,但現在我有一個非常嚴重的問題:我的應用程序偶爾崩潰,我認爲它與幾個線程可能正在訪問和修改indexPathsNeedingImages
時間。
試圖使用鎖定/同步使我的圖像有時結束到錯誤的單元格。所以,我想實現平滑性,它給我一個全局背景隊列,但使用cutom串行隊列。我無法弄清楚當我使用自定義串行隊列時爲什麼我的UI會凍結,以及爲什麼當我使用全局隊列時不會。
一些想法:也許設置cell.imageView.image = image
周邊的100個細胞發生即使image
已經被分配一定的時間。問題可能在這裏,因爲評論這條線使滾動方式更順暢。但我不明白的是,爲什麼滾動是平滑的,當我離開這條線時,我使用了一個全局的後臺優先級隊列(直到應用程序崩潰時拋出一條消息告訴... was mutated while being enumerated
)。
有關如何解決此問題的任何想法?