SemAllush SemAllush - 4 months ago 18
Swift Question

How can I make the screen stop freezing during extensive calculations?

Ok so what I'm trying to do is change the pixel data of a certain image. I want to use a UIView that moves to the right each time it loops as progressbar. However, what is happening is the screen freezes during the calculation and nothing happens until it has finished. The statusbar clock won't update either. Is there a way to move these calculations to the background somehow and still use the screen real estate?

func lock() {

let lockView = UIImageView(image: self.photoBackgroundView.image!)
var progressBar = UIView(frame: CGRectMake(-self.view.width,0,self.view.width,20)
let increment = progressBar.width/self.photoBackgroundView.width
var password = self.textField.text!
if password == "" {
password = " "
}
var currentIndex = 0



let imageRect = CGRectMake(0, 0, self.photoBackgroundView.image!.size.width,self.photoBackgroundView.image!.size.height)

UIGraphicsBeginImageContext(self.photoBackgroundView.image!.size)
let context = UIGraphicsGetCurrentContext()

CGContextSaveGState(context)
CGContextDrawImage(context, imageRect, self.photoBackgroundView.image!.CGImage)
for x in 0...Int(self.photoBackgroundView.image!.size.width) {
print(x)

progressBar.frame.origin.x += (CGFloat(x) * increment)
self.view.addSubView(progressBar)


for y in 0...Int(self.photoBackgroundView.image!.size.height) {
let pointColor = lockView.layer.colorOfPoint(CGPoint(x: x, y: y))

if currentIndex == Array(password.characters).count {
currentIndex = 0
}
let red = encrypt(pointColor.components.red, passwordChar: Array(password.characters)[currentIndex], currentIndex: currentIndex, x: x, y: y)
currentIndex++
if currentIndex == Array(password.characters).count {
currentIndex = 0
}
let green = encrypt(pointColor.components.green, passwordChar: Array(password.characters)[currentIndex], currentIndex: currentIndex, x: x, y: y)
currentIndex++
if currentIndex == Array(password.characters).count {
currentIndex = 0
}
let blue = encrypt(pointColor.components.blue, passwordChar: Array(password.characters)[currentIndex], currentIndex: currentIndex, x: x, y: y)
currentIndex++

CGContextSetRGBFillColor(context, red, green, blue, pointColor.components.alpha)
CGContextFillRect(context, CGRectMake(CGFloat(x), CGFloat(y), 1, 1))

}



}

CGContextRestoreGState(context)
let newImage = UIGraphicsGetImageFromCurrentImageContext()
self.photoBackgroundView.image = newImage
self.slideView.addSubview(photoBackgroundView)
self.view.addSubview(self.slideView)
}

Answer

You can to these calculations in a background thread.

Swift 2:

let priority = DISPATCH_QUEUE_PRIORITY_DEFAULT
dispatch_async(dispatch_get_global_queue(priority, 0)) {
    // Put the calculations here
    dispatch_async(dispatch_get_main_queue()) {
        // any updates of the UI need to be here to do them in the main thread after your background task. For example adding subviews
    }
}

Swift 3:

See this answer