I have a simple test app that submits a few jobs to a NSOperationQueue, then waits for them to finish. I then have a routine that checks the number of jobs in the queue and is supposed to update a value on screen. At the same time it prints the value to the console. The console works exactly as I would expect with a number being printed every ten seconds. The number reduces to zero and the alert is fired. But at no stage does the label (progress) ever change from "Hello".
I have a feeling that rather than being a bug in my code it is a gaping hole in my understanding of Swift. Please help.
My code:
Import UIKit
class TestUpload: UIViewController {
@IBOutlet weak var progress: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
progress.text = "Hello"
// submit some jobs ….
// * I have omitted this code as I don't think it has a problem. * //
let time = dispatch_time(dispatch_time_t(DISPATCH_TIME_NOW), 10 * Int64(NSEC_PER_SEC))
dispatch_after(time, dispatch_get_main_queue()) {
self.showProgress()
}
}
func showProgress() {
while Int(session.operationQueue.operationCount) > 0 {
sleep(10)
print(session.operationQueue.operationCount)
progress.text = String(session.operationQueue.operationCount)
}
let confirmUpload = UIAlertController(title: "Your Tasks have been performed.", message: "Congratulation!", preferredStyle: UIAlertControllerStyle.Alert)
confirmUpload.addAction(UIAlertAction(title: "Ok", style: .Default, handler: { (action: UIAlertAction!) in self.navigationController?.popViewControllerAnimated(true)}))
presentViewController(confirmUpload, animated: true, completion: nil)
}
UI wont be updated until end of showProgress method. So you can do something like below if that's what you after,.
call as a different thread,
NSThread.detachNewThreadSelector("showProgress", toTarget: self, withObject: nil)
and then update UI on main thread
func showProgress() {
while Int(session.operationQueue.operationCount) > 0 {
sleep(10)
print(session.operationQueue.operationCount)
dispatch_async(dispatch_get_main_queue(), { () -> Void in
progress.text = String(session.operationQueue.operationCount)
})
}
dispatch_async(dispatch_get_main_queue(), { () -> Void in
let confirmUpload = UIAlertController(title: "Your Tasks have been performed.”, message: “Congratulation!”, preferredStyle: UIAlertControllerStyle.Alert)
confirmUpload.addAction(UIAlertAction(title: "Ok", style: .Default, handler: { (action: UIAlertAction!) in self.navigationController?.popViewControllerAnimated(true)}))
presentViewController(confirmUpload, animated: true, completion: nil)
})
}
running both in main thread wont solve your problem even if you make it async dispatch