DuckMan
DuckMan

Reputation: 133

NSOperation maxConcurrentOperationCount = 1 still allowing multiple operations of subclass

I have subclassed NSOperation (what is now known as Operation) to perform some async queries in the background. I would like these to be executed one at a time. To this end i have set maxConcurrentOperationCount to 1 however it is still allowing multiple objects in the queue.

I have declared my queue right below the class declaration:

let downloadQueue = OperationQueue()

Then in view did load set the count:

downloadQueue.maxConcurrentOperationCount = 1

Then call the Operation subclass in code:

self.downloadQueue.addOperation(DownloadOperation(col: collectionView, index: indexPath, cell: cell))

And my subclass:

class DownloadOperation : Operation {

var collectionView: UICollectionView
var indexPath: IndexPath
var collectionCell: InnerCollectionCell

init(col: UICollectionView, index: IndexPath, cell: InnerCollectionCell) {
    collectionView = col
    indexPath = index
    collectionCell = cell
}

let mainQueue = OperationQueue.main

override func main() {


    if(isCancelled) {
        return
    }

///
/// Long query that gets objects in background 
/// it is itself an async task
/// there is a completion block in the query
///


}
}

If i keep adding the DownloadOperation to the downloadQueue the tasks keep performing concurrently (async). Is this because the query that I'm running is itself an async task so the code is skipping ahead and assuming the operation is finished before the async query has had a chance to get all the data?

If this is the case how do i go about waiting for completion of the async query to signal the completion of the NSOperation?? The query itself has a completion block but i do not know how to utilise it for this case.

Upvotes: 2

Views: 980

Answers (1)

rmaddy
rmaddy

Reputation: 318874

If the end of the main function is reached, then the operation queue thinks the operation is finished regardless of what other processing your operation may have kicked off in yet another queue. So as far as the operation queue is concerned, it is only running one operation at a time as requested.

The solution is to ensure that your custom operation's main doesn't return until whatever async process it kicks off has fully completed. A common approach is to use a dispatch group or a semaphore. There are plenty of existing questions covering those solutions.

Upvotes: 5

Related Questions