The reason for this question is because of the reactions to this question.
I realized the understanding of the problem was not fully there as well as the reason for the question in the first place. So I am trying to boil down the reason for the other question to this one at it's core.
First a little preface, and some history, I know NSOperation(Queue) existed before GCD, and and they were implemented using threads before dispatch queues.
The next thing is that you need to understand is that by default, meaning no "waiting" methods being use on operations or operation queues (just a standard "addOperation:"), an NSOperation's main method is executed on the underlying queue of the NSOperationQueue asynchronously (e.g. dispatch_async()).
To conclude my preface, I'm questioning the purpose of setting NSOperationQueue.mainQueue.maxConcurrentOperationCount to 1 in this day and age, now that the underlyingQueue is actually the main GCD serial queue (e.g. the return of dispatch_get_main_queue()).
If NSOperationQueue.mainQueue already executes it's operation's main methods serially, why worry about maxConcurrentOperationCount at all?
To see the issue of it being set to 1, please see the example in the referenced question.
It's set to 1 because there's no reason to set it to anything else, and it's probably slightly better to keep it set to 1 for at least three reasons I can think of.
Reason 1
Because
NSOperationQueue.mainQueue'sunderlyingQueueisdispatch_get_main_queue(), which is serial,NSOperationQueue.mainQueueis effectively serial (it could never run more than a single block at a time, even if itsmaxConcurrentOperationCountwere greater than 1).We can check this by creating our own
NSOperationQueue, putting a serial queue in itsunderlyingQueuetarget chain, and setting itsmaxConcurrentOperationCountto a large number.Create a new project in Xcode using the macOS > Cocoa App template with language Objective-C. Replace the
AppDelegateimplementation with this:If you run this, you'll see that operation 1 doesn't start until operation 0 has ended, even though I set
operationQueue.maxConcurrentOperationCountto 100. This happens because there is a serial queue in the target chain ofoperationQueue.underlyingQueue. ThusoperationQueueis effectively serial, even though itsmaxConcurrentOperationCountis not 1.You can play with the code to try changing the structure of the target chain. You'll find that if there is a serial queue anywhere in that chain, only one operation runs at a time.
But if you set
operationQueue.underlyingQueue = concurrentQueue, and do not setconcurrentQueue's target toserialQueue, then you'll see that 64 operations run simultaneously. ForoperationQueueto run operations concurrently, the entire target chain starting with itsunderlyingQueuemust be concurrent.Since the main queue is always serial,
NSOperationQueue.mainQueueis effectively always serial.In fact, if you set
NSOperationQueue.mainQueue.maxConcurrentOperationCountto anything but 1, it has no effect. If you printNSOperationQueue.mainQueue.maxConcurrentOperationCountafter trying to change it, you'll find that it's still 1. I think it would be even better if the attempt to change it raised an assertion. Silently ignoring attempts to change it is more likely to lead to confusion.Reason 2
NSOperationQueuesubmits up tomaxConcurrentOperationCountblocks to itsunderlyingQueuesimultaneously. Since themainQueue.underlyingQueueis serial, only one of those blocks can run at a time. Once those blocks are submitted, it may be too late to use the-[NSOperation cancel]message to cancel the corresponding operations. I'm not sure; this is an implementation detail that I haven't fully explored. Anyway, if it is too late, that is unfortunate as it may lead to a waste of time and battery power.Reason 3
As with mentioned with reason 2,
NSOperationQueuesubmits up tomaxConcurrentOperationCountblocks to itsunderlyingQueuesimultaneously. SincemainQueue.underlyingQueueis serial, only one of those blocks can execute at a time. The other blocks, and any other resources thedispatch_queue_tuses to track them, must sit around idly, waiting for their turns to run. This is a waste of resources. Not a big waste, but a waste nonetheless. IfmainQueue.maxConcurrentOperationCountis set to 1, it will only submit a single block to itsunderlyingQueueat a time, thus preventing GCD from allocating resources uselessly.