Reputation: 3581
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
If I go with method 2, does that mean all my code after dataLengh_kb will be in background thread which is bad?
If I go with either method 1 or method 2, does that mean functionFinished() will be executed too early ?
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
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
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