Evgeniy Kleban Evgeniy Kleban - 4 months ago 21
iOS Question

NSOperation Queue Priority Does Not Work As Expected

I'm studying the

NSOperation
class and tried to simulate a situation, when I need to manage the priority of an operation.

Please consider the following code:

@implementation MyOperation // First custom NSOperation class


- (void)main {

@autoreleasepool {

NSLog(@"First operation start");
}
}

@implementation MySecondOperation // Second custom NSOperation class

- (void)main {

@autoreleasepool {

NSLog(@"Second operation start");
}
}

@implementation ViewController // Other class using NSOperations

- (void)viewDidLoad {

NSOperationQueue *myQueue = [NSOperationQueue new];

MyOperation *firstOperation = [MyOperation new];

MySecondOperation *secondOperation = [MySecondOperation new];

[firstOperation setQueuePriority:NSOperationQueuePriorityLow];
[secondOperation setQueuePriority:NSOperationQueuePriorityHigh];

[myQueue addOperation:secondOperation];
[myQueue addOperation:firstOperation];

}


Code is pretty straightforward. However, you will be surprised to see output:

2015-08-12 20:32:09.433 NSOperationTesting[1181:39809] First operation start
2015-08-12 20:32:09.433 NSOperationTesting[1181:39811] Second operation start


NSOperation with lower priority start before operation, with higher. I know, NSOperationQueue work in FIFO order, but, i specifically set priority of both operations, so why first operation complete first? It suppose to be after second (with higher priority).

Answer Source

You should not use or depend on QueuePriority to set a specific order in which your operations should be executed because you will not have any guarantees that your operations will execute by priority order.

Per documentation:

You should use priority values only as needed to classify the relative priority of non-dependent operations. Priority values should not be used to implement dependency management among different operation objects. If you need to establish dependencies between operations, use the addDependency: method instead.

If you need to execute your operations in a specific order because one of them is dependent on the other you should use the addDependency: method of NSOperation. So you should do something like this:

[firstOperation addDependency: secondOperation];

This will guarantee that firstOperation will execute after secondOperation.