user172902
user172902

Reputation: 3581

How background thread work and when in functions

I have a function that turns out be too slow to run on main thread (200ms). This function is used to determine the size of the image.

extension : UIImage {
    var dataLengh_kb: Int {
        return (UIImageJPEGRepresentation(self, 1.0)?.length)! / 1024
    }
 }

I am using in various places of my app and especially in the following example

 func someFunction() {
    if img.dataLength_kb > MAX_SIZE {
        // Upload to server
    } else {
        someImageView.image = img
    }

    functionFinished()
 }

Since it is too slow, I am thinking to put it in background thread in two ways I am not sure what the difference and impact to my app is either way.

Method 1:

extension : UIImage {

    var size: Float!

    var dataLengh_kb: Int {
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

        size = UIImageJPEGRepresentation(self, 1.0)?.length)! / 1024

        dispatch_async(dispatch_get_main_queue(), ^{
            return size
        })
    })
}

Method 2:

extension : UIImage {

    var size: Float!

    var dataLengh_kb: Int {
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

            return UIImageJPEGRepresentation(self, 1.0)?.length)! / 1024

        dispatch_async(dispatch_get_main_queue(), ^{

        })
    })
 }

My question is

  1. If I go with method 2, does that mean all my code after dataLengh_kb will be in background thread which is bad?

  2. If I go with either method 1 or method 2, does that mean functionFinished() will be executed too early ?

  3. Both method 1 and method 2 complains that I am not returning an Int Value as it is expected to return 'Int'

Upvotes: 0

Views: 93

Answers (2)

Fonix
Fonix

Reputation: 11597

Unfortunately both methods arent going to work, and even if it was going to somehow, the if statement is dependant on the result of the function, so it would have to wait for the background thread to finish anyway... the whole thing needs to be on a background thread. So maybe this will work for you:

 func someFunction() {
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{
       if img.dataLength_kb > MAX_SIZE {
           // Upload to server (this should NOT be asynchronous if possible, it can block the thread at this point because we are already on a background thread and i assume functionFinished() depends on the result so it should wait here)
       } else {
           dispatch_sync(dispatch_get_main_queue()) { 
              someImageView.image = img //all UI changes must be back on the main thread
           }
       }
       dispatch_sync(dispatch_get_main_queue()) { //optional, but i assume some UI changes will happen inside this function
           functionFinished()
       }
    })
 }

disclaimer: have not tested the code so may need some tweaking

Upvotes: 1

Gurdeep
Gurdeep

Reputation: 191

If I go with method 2, does that mean all my code after dataLengh_kb will be in background thread which is bad?

YES

If I go with either method 1 or method 2, does that mean functionFinished() will be executed too early ?

YES

Is Method 1 the correct way to do it ?

NO

UIImageJPEGRepresentation creates an NSData object for the respective image. It is an expensive and CPU hungry object which is not needed here, i.e. just to get size of image.

Ideal way would be :

Int imgSize  = CGImageGetHeight(image.CGImage) * CGImageGetBytesPerRow(image.CGImage)

OR

extension UIImage {

    var sizeInBytes : Int {
      return CGImageGetHeight(self.CGImage) * CGImageGetBytesPerRow(self.CGImage)
     }
}

Upvotes: 2

Related Questions