Hello friends, In the previous article we were talking about What is the Concurrency how many ways to achieve Concurrency/Multithreading iOS and we have promised to come back with the second part. In the following we’re going to focus on OperationQueues and Choosing Between NSOperation and Grand Central Dispatch in iOS.
- GCD is a low-level C API that permits developers to execute tasks concurrently.
- Operation queues, on the opposite hand, are high-level abstraction of the queue model and is made on top of GCD.
- Day by day our applications need to do more and more complicated tasks without compromising their responsiveness.
- Unlike GCD, they don't conform to the First-In-First-Out order.
- NSOperation allows to set dependencies on the operation.
- NSOperation allows to cancel, resume, and restart the operation.
- Imagine when some users, once they are tapping the button and therefore the button downloads some files or a picture. the download task shouldn't block the user interaction otherwise users kill the app or push to the background state. Things get complicated quickly when your application must do quite a couple of tasks. there's not much time to try to heavy add the most work cycle and still provide a responsive interface.
Operation:
Tasks submitted to the operation queue is in the form of NSOperation instance. We discussed in GCD that tasks are submitted in the block. The same can be done here but should be bundled inside the NSOperation instance. You can simply think of NSOperation as a single unit of work.
- NSBlockOperation
- NSInvocationOperation
Operation
class is an abstract class, you do not use it directly but instead subclass or use one of the system-defined subclasses (NSInvocation
orOperation NSBlock
) to perform the actual task. Despite being abstract, the base implementation ofOperation Operation
does include significant logic to coordinate the safe execution of your task. The presence of this built-in logic allows you to focus on the actual implementation of your task, rather than on the glue code needed to ensure it works correctly with other system objects.
NSInvocationOperation:
An operation that manages the execution of a single encapsulated task specified as an invocation. The NSInvocationOperation class is a concrete subclass of NSOperation that you use to initiate an operation that consists of invoking a selector on a specified object. This class implements a non-concurrent operation.NSBlockOperation
In objective C we can create NSInvocationOperation while it’s not available in Swift. @implementation MyCustomClass
- (NSOperation*)taskWithData:(id)data {
NSInvocationOperation* theOp = [[NSInvocationOperation alloc] initWithTarget:self
selector:@selector(myTaskMethod:) object:data];
return theOp;
}
// This is the method that does the actual work of the task.
- (void)myTaskMethod:(id)data {
// Perform the task.
}
@end
@implementation MyCustomClass
- (NSOperation*)taskWithData:(id)data {
NSInvocationOperation* theOp = [[NSInvocationOperation alloc] initWithTarget:self
selector:@selector(myTaskMethod:) object:data];
return theOp;
}
// This is the method that does the actual work of the task.
- (void)myTaskMethod:(id)data {
// Perform the task.
}
@end
NSBlock Operation:
TheNSBlock
class is a concrete subclass ofOperation NSOperation
that manages the concurrent execution of one or more blocks. You can use this object to execute several blocks at once without having to create separate operation objects for each. When executing more than one block, the operation itself is considered finished only when all blocks have finished executing.
// An instance of some Operation subclass
let operation = BlockOperation {
// perform task here
}
let queue = OperationQueue()
queue.addOperation(operation)
// An instance of some Operation subclass
let operation = BlockOperation {
// perform task here
}
let queue = OperationQueue()
queue.addOperation(operation)
Add Operations
func AddOperation() {
let queue = OperationQueue()
let task = BlockOperation { [weak self] in
self?.task1()
}
let task1 = BlockOperation { [weak self] in
self?.task2()
}
queue.addOperation(task)
queue.addOperation(task1)
}
func task1() {
for i in 1...10{
print("--------Task1----\(i)")
}
}
func task2() {
for i in 1...10{
print("++++++++++Task2++++++++\(i)")
// when UI update use main queue
//DispatchQueue.main.async{ [weak self] in
// self.lbldisplay.text = "\(i)"
//}
}
}
++++++++++Task2++++++++1
++++++++++Task2++++++++2
++++++++++Task2++++++++3
++++++++++Task2++++++++4
++++++++++Task2++++++++5
++++++++++Task2++++++++6
++++++++++Task2++++++++7
++++++++++Task2++++++++8
++++++++++Task2++++++++9
++++++++++Task2++++++++10
--------Task1----1
--------Task1----2
--------Task1----3
--------Task1----4
--------Task1----5
--------Task1----6
--------Task1----7
--------Task1----8
--------Task1----9
--------Task1----10
GCD advantage over NSOperation:
- For GCD implementation is very light-weight
- NSOperationQueue is complex and heavy-weight
- GCD is very easy to use - if you want to do something in the background, all you need to do is write the code and dispatch it on a background queue. Doing the same thing with NSOperation is a lot of additional work.
- Grand Central Dispatch is a low-level C API that interacts directly with Unix level of the system.
NSOperation
andNSOperationQueue
are Objective-C classes.
NSOperation advantages over GCD:
Operations
The completion block is called after the dependency operation starts, but it doesn't mean that the first operation didn't end. The operation will not be started until all of its dependencies return true for finished.
class myOperation1 : Operation {
override func main() {
print("op1 working....")
for i in 1...10 {
print("\(i)")
}
}
}
class myOperation2 : Operation {
override func main() {
print("op2 working....")
}
}
let op1 = myOperation1()
let op2 = myOperation2()
op1.completionBlock = {
print("op1 completed")
}
op2.completionBlock = {
print("op2 completed")
}
op2.addDependency(op1)
let opsQue = OperationQueue()
opsQue.addOperations([op1, op2], waitUntilFinished: true)
Output-
op1 working....
1
2
3
4
5
6
7
8
9
10
op2 working....
op1 completed
op2 completed
iii. State of Operation-
A difference between GCD and NSOperation is that NSOperation has a simple description of its state of operation. Different states of operation are often in several states, counting on its current execution status.
iv. Max Number of Operation
class myOperation1 : Operation {
override func main() {
print("op1 working....")
}
}
class myOperation2 : Operation {
override func main() {
print("op2 working....")
}
}
let op1 = myOperation1()
let op2 = myOperation2()
op1.completionBlock = {
print("op1 finished")
}
op2.completionBlock = {
print("op2 finished")
}
op2.addDependency(op1)
let opsQue = OperationQueue()
// setting maxConcurrentOperationCount to 1
opsQue.maxConcurrentOperationCount = 1
opsQue.addOperation(op1)
opsQue.addOperation(op2)
The NSOperationQueue also adds a
When to Use NSOperation and Grand Central Dispatch:
GCD dispatch queues are better for short tasks that should have minimum performance and memory overhead. Everyone asks is when to use dispatch and operation queue my answer that is, it depends on the requirement to explain that let me give you an example, as you are seeing this video on youtube where you can pause, play or skip this video depends upon what you want so in this case I can say you have 100% control over the video however in the case of TV shows this is not possible.
If you are watching a movie on TV then you cannot skip some songs or scenes similarly when you get such requirements where depending on the logical condition you should be able to cancel, pause or play a thread then the choice has to be NSOperationQueue or Operation queue because they have additional methods with help of which you can control your tasks for all the other cases.
You can use dispatch queue they don't have much drawbacks, operation queue probably gives better control over your thread you can set operational dependencies and many more usually.
The dispatch queue is just a single line of code so developers go ahead and use the dispatch queue and not the operational queue. so lets have a look at an example over here here I have an example of a dispatch queue you can see I can just add one line of code.
Thanks for reading!!
0 Comments