multithreading - iOS: Keeping User Interface responsive while images are being loaded in a separate thread -


some context: have uicollectionview display around thousand tiny images, though around 100 of them visible @ same time.

i need load images disk in separate thread, ui not blocked , user can interact app while images still appearing.

to so, i've implemented rob mayoff's answer proper way deal cell reuse background threads? in swift follows, potocell subclass of 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) } 

however, i'm not getting acceptable results: when scroll, ui freezes fraction of second while images being loaded in background. scrolling not smooth enough. moreover, while first 100 images being loaded, not able scroll @ until last image has been displayed. ui still being blocked after implementation of multithreading.

surprisingly, can achieve desired smoothness modifying queue to:

var myqueue = dispatch_get_global_queue(qos_class_background, 0) 

note previosly using custom serial queue.

after change, ui responsive, have serious problem: app crashes occaionally, , think has fact several threads may accessing , modifying indexpathsneedingimages @ same time.

trying use locks/syncronization makes images end wrong cells times. so, achieve smoothness gives me global background queue using cutom serial queue. can't figure out why ui freezing when use custom serial queue , why not when use global one.


some thoughts: maybe setting cell.imageview.image = image around 100 cells takes time though image has been allocated. problem may here, since commenting line makes scroll way smoother. don't understand why scrolling smooth when leave line uncommented , use global background-priority queue (until app crashes throwing message telling ... mutated while being enumerated).

any ideas on how tackle this?

in function should dispatch_async main queue. reason should switch queues when getting data off network or doing task takes time , blocks ui. when asyncing main queue, ui related things should done.

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) } } 

also if let indexpath = indexpath confusing


Comments

Popular posts from this blog

twig - Using Twigbridge in a Laravel 5.1 Package -

Kivy: Swiping (Carousel & ScreenManager) -

jdbc - Not able to establish database connection in eclipse -