If you want to do a series of calculations, and show that progress, you have to do the calculations in a background thread, and then update the UI on the main thread. If you did your calculations in the main thread, your UI would never have a chance to update itself.
But, assuming that you've successfully initiated your time consuming calculations on a background thread, you could then use a timer (or display link) to update your progress bar, for example, define a timer property:
@property (nonatomic, weak) NSTimer *timer;
Then schedule a repeating timer from the main queue and start your background process:
// start the timer
NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:1.0/60.0
target:self
selector:@selector(updateProgress:)
userInfo:nil
repeats:YES];
self.timer = timer;
// use whatever mechanism you want for initiating your background process (though dispatch queues and operation queues may be easier than dealing with threads directly)
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[self startTimeConsumingProcess]
});
You'd then obviously implement an updateProgress:
method that updates your UI:
- (void)updateProgress:(NSTimer *)timer
{
// update the UI progress bar here
}
And don't forget to invalidate
that timer when your calculation is done or when the view is dismissed, because if you don't, the timer will maintain strong reference to your view controller and you'll have a strong reference cycle (aka retain cycle).
By the way, the other logical approach, instead of using a timer, is to just have the background calculation dispatch UI updates that update the progress bar back to the main queue, e.g.
- (void) startSomeTimeConsumingProcess
{
// start time consuming process in background queue
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
BOOL finished = NO;
while (!finished)
{
// do something, updating `finished` when done
// update UI to report the progress in the main queue, though:
dispatch_async(dispatch_get_main_queue(), ^{
// update progress UI here
});
}
});
}
The only consideration with this approach is how quickly this background process dispatches the main queue with progress bar updates. If it updates too quickly, you can backlog the main queue with progress updates. Hence, the appeal of the timer (or display link) based approach, above. But if you're confident that these updates will happen slowly enough, this alternative approach might be easier.