How to Create a Synchronous Wrapper Around an Asynchronous Method

Wrapper Asynchronous methods are the key to keeping your iOS app responsive. Each method running on the main thread has 1/60 of a second to return before it will affect your screen refresh rate. For long-running operations, the typical paradigm is to execute your code on a separate thread (via an abstraction such as dispatch_queue_t or NSOperationQueue), and when it completes, to invoke a completion handler on the main thread. That way the main thread is available to process touch inputs or render UI elements.

However, there are times when you prefer to treat an asynchronous method synchronously. If you are performing unit tests or invoking from a background thread, it is easier to write your code is classic serial fashion. Here is one way to create a synchronous wrapper around an asynchronous method. This example uses a dispatch_semaphore_t (fancy word for “flag”) to suspend the invoking thread, and NSRunLoop to manually advance the run loop until the semaphore signal is received. There are many other ways to accomplish the same thing, so please let me know if you have a better/preferred way. Enjoy!

//Original asynchronous method
- (void)executeInBackgroundWithCompletion:(void(^)(void))completion
{
  NSOperationQueue* callbackQueue = [NSOperationQueue currentQueue];
  [[[NSOperationQueue alloc] init] addOperationWithBlock:^{
    //do something that takes a long time
    [callbackQueue addOperationWithBlock:^{
      if (completion) {
        completion();
      }
    }];
  }];
}

//Synchronous version
- (void)executeInBackgroundAndWait
{
  dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
  [self executeInBackgroundWithCompletion:^{
    dispatch_semaphore_signal(semaphore);
  }];
  while (dispatch_semaphore_wait(semaphore, DISPATCH_TIME_NOW)) {
    [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate dateWithTimeIntervalSinceNow:0]];
  };
}
Advertisements

About Martin Rybak

I am a New York area software developer and MBA with 10+ years of server-side experience on the Microsoft stack. I've also been a native iOS developer since before the days of ARC. I architect and develop full-stack web applications, iOS apps, database systems, and backend services.

2 responses to “How to Create a Synchronous Wrapper Around an Asynchronous Method

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: