Slinky
Slinky

Reputation: 5832

Better way to Trigger Asynchronous Callbacks in Objective-C

I am looking for a better way to do this, if possible.

I have an asynchronous callback that updates a local sqlite database. I set a flag in a singleton variable (archiveUpdateComplete) when the update completes. I sleep in a do-while until the flag gets set to true, then I hydrate my tableview. Would like to remove sleep()! Thanks for any suggestions.

#define kBgQueue dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0)




- (void)viewDidLoad
{



  dispatch_async(kBgQueue, ^{

    //Hydrate word archive table view

       do {
             sleep(1.0);


           } while ([sharedManager archiveUpdateComplete]==NO);



      [self performSelectorOnMainThread:@selector(hydrateWordArchive) withObject:nil waitUntilDone:YES];


      //Run custom activity indicator
      dispatch_async(dispatch_get_main_queue(), ^{
        [MBProgressHUD hideHUDForView:self.view animated:YES];

      });



  });

}

Upvotes: 1

Views: 784

Answers (2)

jkh
jkh

Reputation: 3266

Perhaps I'm missing something, but why don't you just use a completion callback for this?

In other words, you change your computation to "think" in terms of nested blocks. The first async block (on some concurrent queue) does the work of updating the database, and when it's done it dispatches another async block (to the same concurrent queue) which hydrates the tableview. Finally, from that block you dispatch_async yet another block on the main queue which updates the UI, since that's the only bit that needs to execute on the main queue.

Rather than poll, in other words, you want to chain your async operations. See COMPLETION CALLBACKS section of the man page for dispatch_async().

Upvotes: 0

justin
justin

Reputation: 104698

If you need to poll

Polling/sleeping is rarely necessary or good. As an alternative:

  • You can attach an NSTimer to the main thread's run loop.
  • The selector the timer calls can test [sharedManager archiveUpdateComplete]
  • if YES is returned, then
    • invalidate the timer
    • call [MBProgressHUD hideHUDForView:self.view animated:YES];

If you don't need to poll

There are a few immediate alternatives. Which you choose depends on what knows about what:

  • If your manager knows who to message following completion, then the manager can simply message it. If that must occur on the main thread you can use -[NSObject performSelectorOnMainThread:withObject:waitUntilDone:] to forward to the main thread. You may also see this approach with delegates. In the case of a singleton, it doesn't make a lot of sense to take this route.

  • If your manager does not know who is interested in the change/completion, your manager can post a NSNotification after the task has finished (on the current thread or from the main thread).

  • Key Value Observing (KVO) is another option.

Upvotes: 3

Related Questions