user2462794 user2462794 - 3 months ago 11
Swift Question

View doesn't appear before time consuming operation

I've implemented this indicator in my app: https://github.com/vincechan/SwiftLoadingIndicator

Right after this loading spinner comes to front, I want it to spin all the time, for as long as my operation lasts.

In my operation I do some work on images and then show them to the user, but everytime after I click the "run operation" button, app freezes for a few seconds, updates view with the results and then shows the overlay spinner.
I've tried async dispatch like this:

@IBAction func manipulateImage(sender: AnyObject) {
dispatch_async(dispatch_get_main_queue(), {
LoadingOverlayView.show()
});
if let beginImage = CIImage(image: self.imageView.image!) {
var outputImage = OutputImage(sourceImage: beginImage)
//apply CIFilters:
outputImage.applyFilter(FilterType.Grayscale)
outputImage.applyFilter(FilterType.Sepia)
outputImage.applyFilter(FilterType.Vignette)
outputImage.applyFilter(FilterType.Shadow)

let cgimg = self.imageContext.createCGImage(outputImage, fromRect: outputImage.extent)

self.imageView.image = UIImage(CGImage: cgimg)
LoadingOverlayView.hide()
}


but it doesn't work. Also normal method calls, without async dispatch, acts exactly the same.

Answer

You're likely running this code on the UI thread. If so you can dispatch the operation to a background queue as follows:

// we're already on the UI thread, so dispatch to a background queue
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
   // do your background operations ...
   if let beginImage = CIImage(image: self.imageView.image!) {
       var outputImage = OutputImage(sourceImage: beginImage)
       //apply CIFilters:
       outputImage.applyFilter(FilterType.Grayscale)
       outputImage.applyFilter(FilterType.Sepia)
       outputImage.applyFilter(FilterType.Vignette)
       outputImage.applyFilter(FilterType.Shadow)

       let cgimg = self.imageContext.createCGImage(outputImage, fromRect: outputImage.extent)

       // make sure to dispatch UI function back to main queue!
       dispatch_async(dispatch_get_main_queue(), {
               self.imageView.image = UIImage(CGImage: cgimg)

                LoadingOverlayView.hide()
            }); 
     }
});

// we're already on the UI thread, so show the overlay now
LoadingOverlayView.show()
Comments