Question

I am using a NSProgressIndicator in my main thread to update on progress as I run through my entire method. Now when I end up calling an object from a different class file, and wait for that object to return to a value to my main thread, I notice that the NSProgressIndicator will disappear. I understand that this is because the main thread is blocked until I get the return value from the other object.

So my questions is what is the recommended way for updating UI in the main thread without blocking it and having other objects run in the background and return values to the main thread as needed. I know how to use blocks but blockoperations are not allowed to return values. What I need is something that helps this pseudo code:

-(IBAction) main {

//Update progress indicator UI to show progress
//perform an call to another object from another class.
// wait till i get its return value.
//Update progress indicator UI to show progress
// Use this return value to do something.
//Update progress indicator UI to show progress


}

When the call to the other object is made, I notice that the determinate NSProgressIndicator I have completely disappears since the main thread is blocked. Thanks.

Was it helpful?

Solution

Your above code is not the correct approach. Since main never returns, the progress indicator will never update. You must return quickly on the main thread.

Instead, what you want to do is set up a background block that at various points updates the progress indicator on the main thread. So, for instance:

- (IBAction)start:(id)sender {
  dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

  dispatch_async(queue, ^{
    dispatch_async(dispatch_get_main_queue(), ^{[self.progress setProgress:0];});

    // Doing some stuff
    dispatch_async(dispatch_get_main_queue(), ^{[self.progress setProgress:.25];});

    // Doing more stuff
    dispatch_async(dispatch_get_main_queue(), ^{[self.progress setProgress:.75];});
  });
}

(Yes, this causes the queue to retain self, but that's ok here because self is not retaining the queue.)

OTHER TIPS

You can achieve what you are looking for with GCD (Grand Central Dispatch).

Here is an example to get you started:

dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0ul);
    dispatch_async(queue, ^{
        // Perform async operation
                dispatch_sync(dispatch_get_main_queue(), ^{
                    // Update UI
                });
    });

It sounds like your operation should be run in a separate thread which can be done several ways but is probably most easily achieved using NSOperationQueue and either custom NSOperation classes (it's easier than it sounds to set these up) or use of the NSInvokeOperation class.

Then you can send messages back to your class in the main thread using the NSNotificationCenter or set up as an observer using Key-Value Observing (KVO).

Bottom line, you have a variety of choices and to make the best one should have an understanding of the underlying technologies. I'd start with Apple's Threaded Programming Guide personally, then read it a second time to be sure you extracted all the goodness before building out your solution.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top