title: Is the following a safe use of dispatch_set_target_queue()?
body: <p>What I want to do is create an indirect <a href="https://developer.apple.com/documentation/dispatch/1452989-dispatch_set_target_queue?language=objc" rel="nofollow noreferrer">queue targeting</a> the <a href="https://developer.apple.com/documentation/dispatch/1452921-dispatch_get_main_queue?language=objc" rel="nofollow noreferrer">main queue</a>.</p>
  
  <pre><code>dispatch_queue_t myQueue = dispatch_queue_create("com.mydomain.my-main-queue", NULL);
  dispatch_set_target_queue(myQueue, dispatch_get_main_queue());
  </code></pre>
  
  <p>My ultimate goal is to use the queue as the <a href="https://developer.apple.com/documentation/foundation/nsoperationqueue/1415344-underlyingqueue?language=objc" rel="nofollow noreferrer">underlyingQueue</a> property of an <a href="https://developer.apple.com/documentation/foundation/nsoperationqueue?language=objc" rel="nofollow noreferrer">NSOperationQueue</a>, <a href="https://developer.apple.com/documentation/foundation/nsoperationqueue/1415344-underlyingqueue?language=objc" rel="nofollow noreferrer">because Apple's documentation clearly states not to use dispatch_get_main_queue()</a>. Though using an indirect queue it technically is following the documentation.</p>
  
  <p>The reason for all this is because <a href="https://developer.apple.com/documentation/foundation/nsoperationqueue/1409193-mainqueue?language=objc" rel="nofollow noreferrer">NSOperationQueue.mainQueue</a> <strong>is not a safe for asynchronous operations</strong>, because it is globally accessible and it's <a href="https://developer.apple.com/documentation/foundation/nsoperationqueue/1414982-maxconcurrentoperationcount?language=objc" rel="nofollow noreferrer">maxConcurrentOperationCount</a> <strong>is set to 1</strong>. So can easily shoot yourself in the foot with this operation queue.</p>
  
  <p><strong>Update 1</strong></p>
  
  <p>It seems there is a lot of confusion about the basis of what this question assumes an "asynchronous NSOperation" is. To be clear this is based on the concepts in this <a href="https://developer.apple.com/videos/play/wwdc2015/226/" rel="nofollow noreferrer">WWDC session</a> The particular concept is using "operation readiness" and dependency management to manage the tasks in your app, which means asynchronous NSOperations are added to NSOperationQueues to take advantage of this. If you take these concepts to the spirit of this question hopefully the reasoning will make more sense, and you can focus on comparing and contrasting the solution with other ones.</p>
  
  <p><strong>Update 2 - Example of issue:</strong></p>
  
  <pre><code>// VendorManager represents any class that you are not in direct control over.
  
  @interface VendorManager : NSObject
  @end
  
  @implementation VendorManager
  
  + (void)doAnsyncVendorRoutine:(void (^)(void))completion {
      // Need to do some expensive work, make sure we are off the main thread
      dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND 0), ^(void) {
          // Some off main thread background work
          sleep(10);
          // We are done, go back to main thread
          [NSOperationQueue.mainQueue addOperationWithBlock:completion];
      });
  }
  
  @end
  
  
  // MYAsyncBoilerPlateOperation represents all the boilerplate needed
  // to implement a useful asnychronous NSOperation implementation.
  
  @interface MYAlertOperation : MYAsyncBoilerPlateOperation
  @end
  
  @implementation MYAlertOperation
  
  - (void)main {
  
      UIAlertController *alertController = [UIAlertController alertControllerWithTitle:"Vendor"
                                                                               message:"Should vendor do work?"
                                                                        preferredStyle:UIAlertControllerStyleAlert];
      __weak __typeof(self) weakSelf = self;
      [alertController addAction:[UIAlertAction actionWithTitle:@"Yes"
                                                          style:UIAlertActionStyleDefault
                                                        handler:^(UIAlertAction *action) {
                                                            [VendorManager doAnsyncVendorRoutine:^{
                                                                // implemented in MYAsyncBoilerPlateOperation
                                                                [weakSelf completeThisOperation];
                                                            }];
                                                        }]];
      [alertController addAction:[UIAlertAction actionWithTitle:@"No"
                                                          style:UIAlertActionStyleDefault
                                                        handler:^(UIAlertAction *action) {
                                                            [weakSelf cancel];
                                                        }]];
  
      [MYAlertManager sharedInstance] presentAlert:alertController animated:YES];
  }
  
  @end
  
  // MYAlertOperation will never complete.
  // Because of an indirect dependency on operations being run on mainQueue.
  // This example is an issue because mainQueue maxConcurrentOperationCount is 1.
  // This example would not be an issue if maxConcurrentOperationCount was &gt; 1.
  
  [NSOperationQueue.mainQueue addOperation:[[MYAlertOperation alloc] init]];
  </code></pre>
  
  <p><strong>Update 3 - Example 2:</strong></p>
  
  <p>I am not showing the implementation of MyAsyncBlockOperation but you can use <a href="https://gist.github.com/Sorix/57bc3295dc001434fe08acbb053ed2bc" rel="nofollow noreferrer">this as what it's based on in Swift</a>.</p>
  
  <pre><code>// operation.asynchronous is YES, and things are implemented correctly for state changes.
  MyAsyncBlockOperation *operation = [MyAsyncBlockOperation new];
  __weak MyAsyncBlockOperation *weakOperation = operation;
  // executionBlock is simply invoked in main
  // - (void)main { self.executionBlock() };
  operation.executionBlock = ^{
      UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"Vendor"
                                                                               message:@"Should vendor do work?"
                                                                        preferredStyle:UIAlertControllerStyleAlert];
  
      [alertController addAction:[UIAlertAction actionWithTitle:@"Yes"
                                                          style:UIAlertActionStyleDefault
                                                        handler:^(UIAlertAction *action) {
                                                            [[NSOperationQueue mainQueue] addOperationWithBlock:^{
                                                                NSLog(@"Never called");
                                                                [weakOperation completeWithSuccess];
                                                            }];
                                                        }]];
  
      [alertController addAction:[UIAlertAction actionWithTitle:@"No"
                                                          style:UIAlertActionStyleDefault
                                                        handler:^(UIAlertAction *action) {
                                                            [weakOperation cancel];
                                                        }]];
  
      [[UIApplication sharedApplication].keyWindow.rootViewController presentViewController:alertController animated:YES completion:nil];
  }];
  
  operation.completionBlock = ^{
      NSLog(@"If YES, Never called. If NO, called.");
  };
  
  [[NSOperationQueue mainQueue] addOperation:operation];
  </code></pre>
  
  <p>So I thought, why not have another NSOperationQueue? One with it's <a href="https://developer.apple.com/documentation/foundation/nsoperationqueue/1415344-underlyingqueue?language=objc" rel="nofollow noreferrer">underlyingQueue</a> set to the previously mentioned indirect <a href="https://developer.apple.com/documentation/dispatch/dispatch_queue_t" rel="nofollow noreferrer">GCD queue</a> (<em>still following the documentation</em>). So we can have a concurrent NSOperationQueue, legally targeting the serial main <a href="https://developer.apple.com/documentation/dispatch/dispatch_queue_t" rel="nofollow noreferrer">GCD queue</a>, and ultimately ensuring the operations run on the main thread.</p>
  
  <p>Let me know if you want clarification, here is an example of the full code:</p>
  
  <pre><code>NSOperationQueue *asyncSafeMainQueue = [[NSOperationQueue alloc] init];
  asyncSafeMainQueue.qualityOfService = NSQualityOfServiceDefault; // not needed, just for clarity
  dispatch_queue_t underlyingQueue = dispatch_queue_create("com.mydomain.main-thread", NULL);
  dispatch_set_target_queue(underlyingQueue, dispatch_get_main_queue());
  asyncSafeMainQueue.underlyingQueue = underlyingQueue;
  </code></pre>
  
  <p><em>Now... there is a safe operation queue for asynchronous operations that need to run on the main thread, and <strong>without any unnecessary context switching</em>.</strong></p>
  
  <p>Is it safe?</p>