Can I start an NSOperation inside of another NSOperation without a queue? - ios

My application gets the current device location, POSTs this to my server, and returns a dictionary to be displayed in a table view. Currently I am using the CLLocationManager delegate methods and AFJSONRequestOperation (AFNetworking's retrieve-data-through-NSURLConnection-in-NSOperation class) to do the job, but this functionality is inside one view controller method and I'd like to be able to reuse this across other view controllers.
I am planning to make my own NSOperation subclass, but first I wanted to know if there are any unseen pitfalls in having NSOperations (AFJSONRequestOperation) start inside of another NSOperation. Does this work as expected or should I find a way to make a queue with dependencies among the operations?

Scheduling a NSULRL connection operation within a NSOperation will fail unless you schedule it on the main run loop. AFJSONOperation (or any subclass of AFURLOperation) will succeed because under the hood, AFNetworking operations are scheduled on their own NSOperationQueue and on a custom run loop.
So - Yes. Go for it. I use NSOperation subclasses to isolate all of my worker processes. It is much cleaner than flat out GCD in the middle of your VCs or Models.
Caveat - Since all AFNetworking operations are block based and return asynchronously, your NSOperation subclass will need to be concurrent. Apple provides a detailed description of how to build this in their docs for Concurrent NSOperation Subclasses
Optionally - you could just skip building a concurrent NSOperation subclass, and fire your network operation synchronously from within your NSOperation since you're already off of the main queue.

All the NSOperation stuff uses GCD under the hood, and GCD has no issues with nested dispatch_async calls, so I doubt nesting NSOperations will cause you problems as long as your logic is correct.

Related

What is the difference between dispatch_queue and NSOperationQueue? [duplicate]

I'm learning about concurrent programming for iOS. So far I've read about NSOperation/NSOperationQueue and GCD. What are the reasons for using NSOperationQueue over GCD and vice versa?
Sounds like both GCD and NSOperationQueue abstract away the explicit creation of NSThreads from the user. However the relationship between the two approaches isn't clear to me so any feedback to appreciated!
GCD is a low-level C-based API that enables very simple use of a task-based concurrency model. NSOperation and NSOperationQueue are Objective-C classes that do a similar thing. NSOperation was introduced first, but as of 10.5 and iOS 2, NSOperationQueue and friends are internally implemented using GCD.
In general, you should use the highest level of abstraction that suits your needs. This means that you should usually use NSOperationQueue instead of GCD, unless you need to do something that NSOperationQueue doesn't support.
Note that NSOperationQueue isn't a "dumbed-down" version of GCD; in fact, there are many things that you can do very simply with NSOperationQueue that take a lot of work with pure GCD. (Examples: bandwidth-constrained queues that only run N operations at a time; establishing dependencies between operations. Both very simple with NSOperation, very difficult with GCD.) Apple's done the hard work of leveraging GCD to create a very nice object-friendly API with NSOperation. Take advantage of their work unless you have a reason not to.
Caveat:
On the other hand, if you really just need to send off a block, and don't need any of the additional functionality that NSOperationQueue provides, there's nothing wrong with using GCD. Just be sure it's the right tool for the job.
In line with my answer to a related question, I'm going to disagree with BJ and suggest you first look at GCD over NSOperation / NSOperationQueue, unless the latter provides something you need that GCD doesn't.
Before GCD, I used a lot of NSOperations / NSOperationQueues within my applications for managing concurrency. However, since I started using GCD on a regular basis, I've almost entirely replaced NSOperations and NSOperationQueues with blocks and dispatch queues. This has come from how I've used both technologies in practice, and from the profiling I've performed on them.
First, there is a nontrivial amount of overhead when using NSOperations and NSOperationQueues. These are Cocoa objects, and they need to be allocated and deallocated. In an iOS application that I wrote which renders a 3-D scene at 60 FPS, I was using NSOperations to encapsulate each rendered frame. When I profiled this, the creation and teardown of these NSOperations was accounting for a significant portion of the CPU cycles in the running application, and was slowing things down. I replaced these with simple blocks and a GCD serial queue, and that overhead disappeared, leading to noticeably better rendering performance. This wasn't the only place where I noticed overhead from using NSOperations, and I've seen this on both Mac and iOS.
Second, there's an elegance to block-based dispatch code that is hard to match when using NSOperations. It's so incredibly convenient to wrap a few lines of code in a block and dispatch it to be performed on a serial or concurrent queue, where creating a custom NSOperation or NSInvocationOperation to do this requires a lot more supporting code. I know that you can use an NSBlockOperation, but you might as well be dispatching something to GCD then. Wrapping this code in blocks inline with related processing in your application leads in my opinion to better code organization than having separate methods or custom NSOperations which encapsulate these tasks.
NSOperations and NSOperationQueues still have very good uses. GCD has no real concept of dependencies, where NSOperationQueues can set up pretty complex dependency graphs. I use NSOperationQueues for this in a handful of cases.
Overall, while I usually advocate for using the highest level of abstraction that accomplishes the task, this is one case where I argue for the lower-level API of GCD. Among the iOS and Mac developers I've talked with about this, the vast majority choose to use GCD over NSOperations unless they are targeting OS versions without support for it (those before iOS 4.0 and Snow Leopard).
GCD is a low-level C-based API.
NSOperation and NSOperationQueue are Objective-C classes.
NSOperationQueue is objective C wrapper over GCD.
If you are using NSOperation, then you are implicitly using Grand Central Dispatch.
GCD advantage over NSOperation:
i. implementation
For GCD implementation is very light-weight
NSOperationQueue is complex and heavy-weight
NSOperation advantages over GCD:
i. Control On Operation
you can Pause, Cancel, Resume an NSOperation
ii. Dependencies
you can set up a dependency between two NSOperations
operation will not started until all of its dependencies return true for finished.
iii. State of Operation
can monitor the state of an operation or operation queue.
ready ,executing or finished
iv. Max Number of Operation
you can specify the maximum number of queued operations that can run simultaneously
When to Go for GCD or NSOperation
when you want more control over queue (all above mentioned) use NSOperation
and for simple cases where you want less overhead
(you just want to do some work "into the background" with very little additional work) use GCD
ref:
https://cocoacasts.com/choosing-between-nsoperation-and-grand-central-dispatch/
http://iosinfopot.blogspot.in/2015/08/nsthread-vs-gcd-vs-nsoperationqueue.html
http://nshipster.com/nsoperation/
Another reason to prefer NSOperation over GCD is the cancelation mechanism of NSOperation. For example, an App like 500px that shows dozens of photos, use NSOperation we can cancel requests of invisible image cells when we scroll table view or collection view, this can greatly improve App performance and reduce memory footprint. GCD can't easily support this.
Also with NSOperation, KVO can be possible.
Here is an article from Eschaton which is worth reading.
GCD is indeed lower-level than NSOperationQueue, its major advantage is that its implementation is very light-weight and focused on lock-free algorithms and performance.
NSOperationQueue does provide facilities that are not available in GCD, but they come at non-trivial cost, the implementation of NSOperationQueue is complex and heavy-weight, involves a lot of locking, and uses GCD internally only in a very minimal fashion.
If you need the facilities provided by NSOperationQueue by all means use it, but if GCD is sufficient for your needs, I would recommend using it directly for better performance, significantly lower CPU and power cost and more flexibility.
Both NSQueueOperations and GCD allow executing heavy computation task in the background on separate threads by freeing the UI Application Main Tread.
Well, based previous post we see NSOperations has addDependency so that you can queue your operation one after another sequentially.
But I also read about GCD serial Queues you can create run your operations in the queue using dispatch_queue_create. This will allow running a set of operations one after another in a sequential manner.
NSQueueOperation Advantages over GCD:
It allows to add dependency and allows you to remove dependency so for one transaction you can run sequential using dependency and for other transaction run concurrently while GCD
doesn't allow to run this way.
It is easy to cancel an operation if it is in the queue it can be stopped if it is running.
You can define the maximum number of concurrent operations.
You can suspend operation which they are in Queue
You can find how many pending operations are there in queue.
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.
The advantage of NSOperation is that (a) you have a real object that you can send messages to, and (b) that you can cancel an NSOperation. That's not trivial. You need to subclass NSOperation, you have to write your code correctly so that cancellation and correctly finishing a task both work correctly. So for simple things you use GCD, and for more complicated things you create a subclass of NSOperation. (There are subclasses NSInvocationOperation and NSBlockOperation, but everything they do is easier done with GCD, so there is no good reason to use them).
Well, NSOperations are simply an API built on top of Grand Central Dispatch. So when you’re using NSOperations, you’re really still using Grand Central Dispatch.
It’s just that NSOperations give you some fancy features that you might like. You can make some operations dependent on other operations, reorder queues after you sumbit items, and other things like that.
In fact, ImageGrabber is already using NSOperations and operation queues! ASIHTTPRequest uses them under the hood, and you can configure the operation queue it uses for different behavior if you’d like.
So which should you use? Whichever makes sense for your app. For this app it’s pretty simple so we just used Grand Central Dispatch directly, no need for the fancy features of NSOperation. But if you need them for your app, feel free to use it!
I agree with #Sangram and other answers but want to add few points. Correct me if I am wrong.
I think now a days first two points of #Sangram's answer are not valid (i. Control On Operation ii. Dependencies). We can achieve these two by using GCD also. Trying to explain by code(do not focus on quality of code, this is for reference purpose only)
func methodsOfGCD() {
let concurrentQueue = DispatchQueue.init(label: "MyQueue", qos: .background, attributes: .concurrent)
//We can suspend and resume Like this
concurrentQueue.suspend()
concurrentQueue.resume()
//We can cancel using DispatchWorkItem
let workItem = DispatchWorkItem {
print("Do something")
}
concurrentQueue.async(execute: workItem)
workItem.cancel()
//Cam add dependency like this.
//Operation 1
concurrentQueue.async(flags: .barrier) {
print("Operation1")
}
//Operation 2
concurrentQueue.async(flags: .barrier) {
print("Operation2")
}
//Operation 3.
//Operation 3 have dependency on Operation1 and Operation2. Once 1 and 2 will finish will execute Operation 3. Here operation queue work as a serial queue.
concurrentQueue.async(flags: .barrier) {
print("Operation3")
}
}

What is the best networking solution for a complex multithreaded app?

I have a streaming iOS app that captures video to Wowza servers.
It's a beast, and it's really finicky.
I'm grabbing configuration settings from a php script that shoots out JSON.
Now that I've implemented that, I've run into some strange threading issues. My app connects to the host, says its streaming, but never actually sends packets.
Getting rid of the remote configuration NSURLConnection (which I've made sure is properly formatted) delegate fixes the problem. So I'm thinking either some data is getting misconstrued across threads or something like that.
What will help me is knowing:
Are NSURLConnection delegate methods called on the main thread?
Will nonatomic data be vulnerable in a delegate method?
When dealing with a complex threaded app, what are the best practices for grabbing data from the web?
Have you looked at AFNetworking?
http://www.raywenderlich.com/30445/afnetworking-crash-course
https://github.com/AFNetworking/AFNetworking
It's quite robust and helps immensely with the threading, and there are several good tutorials.
Are NSURLConnection delegate methods called on the main thread?
Yes, on request completion it gives a call back on the main thread if you started it on the main thread.
Will nonatomic data be vulnerable in a delegate method?
Generally collection values (like array) are vulnerable with multiple threads; the rest shouldn't create anything other than a race problem.
When dealing with a complex threaded app, what are the best practices for grabbing data from the web?
I feel it's better to use GCD for handling your threads, and asynchronous retrieval using NSURLConnection should be helpful. There are few network libraries available to do the boilerplate code for you, such as AFNetworking, and ASIHTTPRequest (although that is a bit old).
Are NSURLConnection delegate methods called on the main thread?
Delegate methods can be executed on a NSOperationQueue or a thread. If you not explicitly schedule the connection, it will use the thread where it receives the start message. This can be the main thread, but it can also any other secondary thread which shall also have a run loop.
You can set the thread (indirectly) with method
- (void)scheduleInRunLoop:(NSRunLoop *)aRunLoop forMode:(NSString *)mode
which sets the run loop which you retrieved from the current thread. A run loop is associated to a thread in a 1:1 relation. That is, in order to set a certain thread where the delegate methods shall be executed, you need to execute on this thread, retrieve the Run Loop from the current thread and send scheduleInRunLoop:forMode: to the connection.
Setting up a dedicated secondary thread requires, that this thread will have a Run Loop. Ensuring this is not always straight forward and requires a "hack".
Alternatively, you can use method
- (void)setDelegateQueue:(NSOperationQueue *)queue
in order to set the queue where the delegate methods will be executed. Which thread will be actually used for executing the delegates is then undetermined.
You must not use both methods - so schedule on a thread OR a queue. Please consult the documentation for more information.
Will nonatomic data be vulnerable in a delegate method?
You should always synchronize access to shared resources - even for integers. On certain multiprocessor systems it is not even guaranteed that accesses to a shared integer is safe. You will have to use memory barriers on both threads in order to guarantee that.
You might utilize serial queues (either NSOperationQueue or dispatch queue) to guarantee safe access to shared resources.
When dealing with a complex threaded app, what are the best practices for grabbing data from the web?
Utilize queues, as mentioned, then you don't have to deal with threads. "Grabbing data" is not only a threading problem ;)
If you prefer a more specific answer you would need to describe your problem in more detail.
To answer your first question: The delegate methods are called on the thread that started the asynchronous load operation for the associated NSURLConnection object.

NSOperation using GCD, ensure all on the same thread

I have a 'concurrent' NSOperation, and during it's work it uses some controller classes that internally use GCD. When these controller classes return with their completion block, the completion block is on another thread.
I know I could store the current thread in the operation start method and run performSelectorOnThread:, but ideally I would like to wrap the completion in a GCD block and dispatch onto the same thread as the operation started on. Is this even possible with GCD, as I can only specify a queue to dispatch to.
What's the best way to bring this work back onto the same thread that the operation started on? Apart from what I already suggested... unless this is the best way.
When the operation is completed the UI update or any other related things has to be done on main thread. The following link might be useful to you about CGD.
http://www.raywenderlich.com/4295/multithreading-and-grand-central-dispatch-on-ios-for-beginners-tutorial
I don't think this is really possible/advisable. Since iOS 4 onwards, NSOperation is using GCD , and as GCD is managing my threads - I don't think I should be keeping references to them.
I did find some util methods for executing blocks of code on a particular thread. See Practical Blocks by Mike Ash or this article doing similar thing.
As my goal was to keep my core data calls on the same thread, instead I opted to upgrade my code to use parent/child managed object contexts with NSPrivateQueueConcurrencyType, and then used performBlock: on the managed object context to ensure all my call backs on the separate threads got executed correctly by core data.

iOS. Do NSURLConnection and UIView's setNeedsDisplay rely on GCD for asynchronous behavior?

I am doing a lot of GCD and asynchronous rendering and data retrieval work lately and I really need to nail the mental model about how asynchronous is done.
I want to focus on setNeedsDisplay and the NSURLConnectionDelegate suite of methods.
Is it correct to call setNeedsDisplay asynchronous? I often call it via dispatch_async(dispatch_get_main_queue(), ^{}) which confuses me.
The NSURLConnectionDelegate callbacks are described as asynchronous but are they not actually concurrently run on the main thread/runloop. I am a but fuzzy on the distinction here.
More generally in the modern iOS era of GCD what is the best practice for making GCD and these methods play nice together. I'm just looking for general guidelines here since I use them regularly and am just trying not to get myself in trouble.
Cheers,
Doug
No, you generally don't call setNeedsDisplay asynchronously. But if you're invoking this from a queue other than the main queue (which I would guess you are), then you should note that you never should do UI updates from background queues. You always run those from the main queue. So, this looks like the very typical pattern of dispatching a UI update from a background queue to the main queue.
NSURLConnection is described as asynchronous because when you invoke it, unless you used sendSynchronousRequest, your app immediately returns while the connection progresses. The fact that the delegate events are on the main queue is not incompatible with the notion that the connection, itself, is asynchronous. Personally, I would have thought it bad form if I can some delegate methods that were not being called from the same queue from which the process was initiated, unless that was fairly explicit via the interface.
To the question of your question's title, whether NSURLConnection uses GCD internally, versus another concurrency technology (NSOperationQueue, threads, etc.), that's an internal implementation issue that we, as application developers, don't generally worry about.
To your final, follow-up question regarding guidelines, I'd volunteer the general rule I alluded to above. Namely, all time consuming processes that would block your user interface should be dispatched to background queue, but any subsequent UI updates required by the background queue should be dispatched back to the main queue. That's the most general rule of thumb I can think of that encapsulates why we generally do concurrent programming and how to do so properly.

NSOperation vs Grand Central Dispatch

I'm learning about concurrent programming for iOS. So far I've read about NSOperation/NSOperationQueue and GCD. What are the reasons for using NSOperationQueue over GCD and vice versa?
Sounds like both GCD and NSOperationQueue abstract away the explicit creation of NSThreads from the user. However the relationship between the two approaches isn't clear to me so any feedback to appreciated!
GCD is a low-level C-based API that enables very simple use of a task-based concurrency model. NSOperation and NSOperationQueue are Objective-C classes that do a similar thing. NSOperation was introduced first, but as of 10.5 and iOS 2, NSOperationQueue and friends are internally implemented using GCD.
In general, you should use the highest level of abstraction that suits your needs. This means that you should usually use NSOperationQueue instead of GCD, unless you need to do something that NSOperationQueue doesn't support.
Note that NSOperationQueue isn't a "dumbed-down" version of GCD; in fact, there are many things that you can do very simply with NSOperationQueue that take a lot of work with pure GCD. (Examples: bandwidth-constrained queues that only run N operations at a time; establishing dependencies between operations. Both very simple with NSOperation, very difficult with GCD.) Apple's done the hard work of leveraging GCD to create a very nice object-friendly API with NSOperation. Take advantage of their work unless you have a reason not to.
Caveat:
On the other hand, if you really just need to send off a block, and don't need any of the additional functionality that NSOperationQueue provides, there's nothing wrong with using GCD. Just be sure it's the right tool for the job.
In line with my answer to a related question, I'm going to disagree with BJ and suggest you first look at GCD over NSOperation / NSOperationQueue, unless the latter provides something you need that GCD doesn't.
Before GCD, I used a lot of NSOperations / NSOperationQueues within my applications for managing concurrency. However, since I started using GCD on a regular basis, I've almost entirely replaced NSOperations and NSOperationQueues with blocks and dispatch queues. This has come from how I've used both technologies in practice, and from the profiling I've performed on them.
First, there is a nontrivial amount of overhead when using NSOperations and NSOperationQueues. These are Cocoa objects, and they need to be allocated and deallocated. In an iOS application that I wrote which renders a 3-D scene at 60 FPS, I was using NSOperations to encapsulate each rendered frame. When I profiled this, the creation and teardown of these NSOperations was accounting for a significant portion of the CPU cycles in the running application, and was slowing things down. I replaced these with simple blocks and a GCD serial queue, and that overhead disappeared, leading to noticeably better rendering performance. This wasn't the only place where I noticed overhead from using NSOperations, and I've seen this on both Mac and iOS.
Second, there's an elegance to block-based dispatch code that is hard to match when using NSOperations. It's so incredibly convenient to wrap a few lines of code in a block and dispatch it to be performed on a serial or concurrent queue, where creating a custom NSOperation or NSInvocationOperation to do this requires a lot more supporting code. I know that you can use an NSBlockOperation, but you might as well be dispatching something to GCD then. Wrapping this code in blocks inline with related processing in your application leads in my opinion to better code organization than having separate methods or custom NSOperations which encapsulate these tasks.
NSOperations and NSOperationQueues still have very good uses. GCD has no real concept of dependencies, where NSOperationQueues can set up pretty complex dependency graphs. I use NSOperationQueues for this in a handful of cases.
Overall, while I usually advocate for using the highest level of abstraction that accomplishes the task, this is one case where I argue for the lower-level API of GCD. Among the iOS and Mac developers I've talked with about this, the vast majority choose to use GCD over NSOperations unless they are targeting OS versions without support for it (those before iOS 4.0 and Snow Leopard).
GCD is a low-level C-based API.
NSOperation and NSOperationQueue are Objective-C classes.
NSOperationQueue is objective C wrapper over GCD.
If you are using NSOperation, then you are implicitly using Grand Central Dispatch.
GCD advantage over NSOperation:
i. implementation
For GCD implementation is very light-weight
NSOperationQueue is complex and heavy-weight
NSOperation advantages over GCD:
i. Control On Operation
you can Pause, Cancel, Resume an NSOperation
ii. Dependencies
you can set up a dependency between two NSOperations
operation will not started until all of its dependencies return true for finished.
iii. State of Operation
can monitor the state of an operation or operation queue.
ready ,executing or finished
iv. Max Number of Operation
you can specify the maximum number of queued operations that can run simultaneously
When to Go for GCD or NSOperation
when you want more control over queue (all above mentioned) use NSOperation
and for simple cases where you want less overhead
(you just want to do some work "into the background" with very little additional work) use GCD
ref:
https://cocoacasts.com/choosing-between-nsoperation-and-grand-central-dispatch/
http://iosinfopot.blogspot.in/2015/08/nsthread-vs-gcd-vs-nsoperationqueue.html
http://nshipster.com/nsoperation/
Another reason to prefer NSOperation over GCD is the cancelation mechanism of NSOperation. For example, an App like 500px that shows dozens of photos, use NSOperation we can cancel requests of invisible image cells when we scroll table view or collection view, this can greatly improve App performance and reduce memory footprint. GCD can't easily support this.
Also with NSOperation, KVO can be possible.
Here is an article from Eschaton which is worth reading.
GCD is indeed lower-level than NSOperationQueue, its major advantage is that its implementation is very light-weight and focused on lock-free algorithms and performance.
NSOperationQueue does provide facilities that are not available in GCD, but they come at non-trivial cost, the implementation of NSOperationQueue is complex and heavy-weight, involves a lot of locking, and uses GCD internally only in a very minimal fashion.
If you need the facilities provided by NSOperationQueue by all means use it, but if GCD is sufficient for your needs, I would recommend using it directly for better performance, significantly lower CPU and power cost and more flexibility.
Both NSQueueOperations and GCD allow executing heavy computation task in the background on separate threads by freeing the UI Application Main Tread.
Well, based previous post we see NSOperations has addDependency so that you can queue your operation one after another sequentially.
But I also read about GCD serial Queues you can create run your operations in the queue using dispatch_queue_create. This will allow running a set of operations one after another in a sequential manner.
NSQueueOperation Advantages over GCD:
It allows to add dependency and allows you to remove dependency so for one transaction you can run sequential using dependency and for other transaction run concurrently while GCD
doesn't allow to run this way.
It is easy to cancel an operation if it is in the queue it can be stopped if it is running.
You can define the maximum number of concurrent operations.
You can suspend operation which they are in Queue
You can find how many pending operations are there in queue.
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.
The advantage of NSOperation is that (a) you have a real object that you can send messages to, and (b) that you can cancel an NSOperation. That's not trivial. You need to subclass NSOperation, you have to write your code correctly so that cancellation and correctly finishing a task both work correctly. So for simple things you use GCD, and for more complicated things you create a subclass of NSOperation. (There are subclasses NSInvocationOperation and NSBlockOperation, but everything they do is easier done with GCD, so there is no good reason to use them).
Well, NSOperations are simply an API built on top of Grand Central Dispatch. So when you’re using NSOperations, you’re really still using Grand Central Dispatch.
It’s just that NSOperations give you some fancy features that you might like. You can make some operations dependent on other operations, reorder queues after you sumbit items, and other things like that.
In fact, ImageGrabber is already using NSOperations and operation queues! ASIHTTPRequest uses them under the hood, and you can configure the operation queue it uses for different behavior if you’d like.
So which should you use? Whichever makes sense for your app. For this app it’s pretty simple so we just used Grand Central Dispatch directly, no need for the fancy features of NSOperation. But if you need them for your app, feel free to use it!
I agree with #Sangram and other answers but want to add few points. Correct me if I am wrong.
I think now a days first two points of #Sangram's answer are not valid (i. Control On Operation ii. Dependencies). We can achieve these two by using GCD also. Trying to explain by code(do not focus on quality of code, this is for reference purpose only)
func methodsOfGCD() {
let concurrentQueue = DispatchQueue.init(label: "MyQueue", qos: .background, attributes: .concurrent)
//We can suspend and resume Like this
concurrentQueue.suspend()
concurrentQueue.resume()
//We can cancel using DispatchWorkItem
let workItem = DispatchWorkItem {
print("Do something")
}
concurrentQueue.async(execute: workItem)
workItem.cancel()
//Cam add dependency like this.
//Operation 1
concurrentQueue.async(flags: .barrier) {
print("Operation1")
}
//Operation 2
concurrentQueue.async(flags: .barrier) {
print("Operation2")
}
//Operation 3.
//Operation 3 have dependency on Operation1 and Operation2. Once 1 and 2 will finish will execute Operation 3. Here operation queue work as a serial queue.
concurrentQueue.async(flags: .barrier) {
print("Operation3")
}
}

Resources