UI does not refresh when main thread is blocked in Cocoa app

I am using NSProgressIndicator in my main thread to update the progress as I go through my entire method. Now when I finish calling an object from another class file and wait for that object to return to value on my main thread, I noticed that the NSProgressIndicator disappears. I understand this is because the main thread is blocking until I get the return value from another object.

So my questions is the recommended way to update the UI on the main thread without blocking it and the rest of the objects run in the background and return values ​​to the main thread as needed. I know how to use blocks, but blockoperations don't allow values ​​to be returned. I need something that helps this pseudocode:

-(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 a call to another object is made, I notice that the specific NSProgressIndicator I completely disappear from the moment the main thread blocked. Thank.

+3


source to share


3 answers


Your code above doesn't match. Since it main

never returns, the progress bar will never update. You should quickly return to the main stream.

Instead, you want to create a background block that updates the progress bar of the main thread at various points. For example:



- (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 forces the queue to persist self

, but that's okay because it self

doesn't persist the queue.)

+9


source


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

Here's 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
                });
    });

      

+4


source


It sounds like your operation needs to run on a separate thread, which can be done in a number of ways, but is probably most easily accomplished using NSOperationQueue and custom NSOperation classes (it's easier than it sounds to set them up) or using the NSInvokeOperation class.

You can then post messages back to your class on the main thread using NSNotificationCenter, or configure as an observer using Key Value Observing (KVO).

At the bottom, you have a choice, and to do the best you need to understand the underlying technology. I would start with the Apple Threading Programming Guide in person and then read it a second time to make sure you get all the goodness before building your solution.

0


source







All Articles