Operations are a flexible way to model your app's business logic, but they can do so much more. See how NSOperation forms the heart of the WWDC app, and how using features like dependencies, readiness, and composition allow you to quickly and easily build dynamic and complex apps.
[ Music ]
PHILIPPE HAUSLER: Good morning.
My name is Philippe Hausler.
I work in the Frameworks Group, on Foundation.
And today we are going to talk
about NSOperation and NSOperationQueue.
These are two extremely powerful classes
that can transform your application
from running tasks linearly to a hybrid scenario
of both the object-orientated
and functionally asynchronous concepts.
Now, I am pretty sure that all
of you have seen this application.
The WWDC app uses NSOperation
and NSOperationQueue extensively.
To be able to accomplish numerous different tasks all the
way from downloading content from the Internet all the way
to synchronizing the database as well as even concepts
like presenting alerts or displaying videos.
And here to take you more in depth of NSOperation
and NSOperationQueue and how it actually was used to be able
to implement the WWDC app is Dave DeLong.
DAVE DeLONG: Thanks, Philippe.
So, my name is Dave DeLong, and I am a Frameworks Evangelist
at Apple, and I am also the primary engineer
on the WWDC app, which hopefully you are all familiar with.
Today we are going to be covering three main areas
of the WWDC app and NSOperation.
First, we are going to go over the core concepts of NSOperation
and how you can understand its API and take advantage
of its powerful state machine.
Next, we are going to go beyond those basics and look
at the challenges of the WWDC app across
and how we solved them.
And finally, we are going to talk about some sample code
that we have provided for you.
So first, let's look at some core concepts.
Any time you use an NSOperation,
you will always be using an NSOperationQueue.
And the way to think about an NSOperationQueue is
that it's a high-level dispatch queue.
Hopefully you are all familiar with dispatch queues
from using Grand Central Dispatch.
Now, by providing a wrapper around an NSOperationQueue,
we can gain some additional functionality.
For example, NSOperationQueue makes it very easy
to cancel operations that have not yet begun executing.
While you can perform cancellation of dispatch blocks,
it is somewhat tricky to do so,
but NSOperationQueue makes this quite easy.
Another thing that you get
with NSOperationQueue is a property called the max
concurrent operation count.
And to understand what this is, let's take a look
at a little animation.
If we set the max concurrent operation count
of an NSOperationQueue to be 1,
then we essentially make our NSOperationQueue
into a serial operation queue.
So let's load up a bunch of operations onto this queue.
With the max concurrent operation count of 1,
the queue will pull off these operations one by one
and execute them in order.
The next operation will not begin executing
until the previous one has finished.
That's a serial queue.
However, by default, the value
of this property is a default value,
which means as many as the system allows.
So this means that our operation queue can perform multiple
operations simultaneously as system resources allow.
So in this case, our operation queue might be performing two
operations at once.
The ability to change the behavior of an operation queue
like this can be very powerful.
We don't have to decide this at creation time
of our operation queue.
So that's NSOperationQueue.
Now let's take a look at NSOperation.
Where the queue is a high-level wrapper around a dispatch queue,
you can think of an NSOperation as a high-level wrapper
around a dispatch block.
Now, in general, NSOperations run for a little bit longer
than you would expect a block to run,
so blocks usually take a few nanoseconds,
maybe at most a millisecond, to execute.
NSOperations, on the other hand, can be much longer, for anywhere
from a couple of milliseconds to even several minutes,
as we will talk about later.
The other thing that's really nice about an NSOperation is
that since it's a class, you can subclass it
and provide your own custom logic on how it executes.
So in order to subclass NSOperation,
let's take a look at its lifecycle.
When you create an NSOperation, it always starts off in a state
that we call the pending state.
So this is the operation when it's initialized
and as it's being put onto its operation queue.
Now, at some point, the operation is going
to become ready to execute, and it enters the ready state.
And after it becomes ready, the operation queue will pull it off
of the queue and begin executing it.
And like I said, this execution can be anywhere from a couple
of milliseconds to several minutes to even longer.
After execution finishes,
the operation enters the finish state, its final state.
So that's pretty simple.
The other thing that an operation can do is
at any point, it can enter a canceled state.
So let's take a look at cancellation.
Cancellation on an NSOperation is defined
as a simple Boolean property, is canceled.
And the important thing to understand
about this property is that it only changes the state
of the property.
When you cancel an operation, all that's happening is
that a Boolean value is getting flipped.
So as you subclass NSOperation, it is up to you
to decide what it means for your NSOperation to be canceled.
So, for example, if your operation is performing a
network task, then maybe canceling your operation is akin
to canceling your network communication.
Or perhaps if you are performing some sort
of database transaction in your operation,
then perhaps canceling your operation would be
like discarding that transaction.
So as you subclass NSOperation,
be sure to observe this value changing and react appropriately
if there's any reaction you need to do.
The other thing to be aware
of with cancellation is it is susceptible to race conditions.
What do I mean by this?
Well, let's consider an operation that's executing
in the background, and maybe in your UI you have a cancel button
that would cancel this operation.
If the user taps the cancel button,
it's going to take a small amount of time for that message,
to cancel, to move from the main queue
to the operation in the background.
And if in that small window
of time your operation finishes executing,
then your operation will actually never be canceled
because an operation cannot go from the finished state
to the canceled state.
So it is important to understand that just because you try
to cancel an operation, there are some cases
where it won't actually cancel.
However, if you do need to cancel an operation,
it is very easy to do so.
All you need to do is call the cancel method.
So that's cancellation.
Now let's take a look at this other interesting state
The readiness of an NSOperation, like cancellation,
is defined as a simple Boolean property, is ready.
And what this property means is
that the operation is ready to execute.
So let's take a look at how this interacts with operations
on an operation queue.
So again, we've got our serial operation queue,
and we are going to load up a bunch of operations,
and they are all in the initial blue pending state.
Now, the first operation
to enter the ready state is the first operation
that will be executed, even, for example, in this case,
if it's the fourth operation that was put onto the queue.
So once the operation is ready, it begins executing.
Then, as other operations become ready,
they are pulled off the queue and executed.
And in this case, since we have a serial queue,
only executing one at a time, if two operations become ready
at the same time, then the first one
that has a higher priority will be pulled off first,
and then the second one will be executed.
And then, as the other operations become ready,
they are also pulled off the queue and executed.
So that's brief look at readiness.
Now, what can we do with this?
Well, we can make dependencies.
Dependencies are a way for us to express a strict ordering
between our operations, that first we want
to execute this thing, and then we want to execute that thing.
And the neat thing
about dependencies is they provide the base definition
for what it means for an operation to be ready.
By default, an operation will become ready if all
of its dependencies have finished executing.
This is behavior that you get for free.
The other neat thing about dependencies is
that they are not limited by operation queues.
Now, what do I mean by this?
If you have two operation queues in your application,
operations in the first queue can be dependent
on the operations in the second queue.
And we are going to see later how this can enable some really
Now, setting up dependencies amongst your operations,
again, is extremely simple.
All we need to do is use the add dependency method.
So in this case, operation B will become dependent
on the successful exectution of operation A.
And so operation B will not execute until after operation A.
This is guaranteed.
Now, with dependencies, we can run into a couple of problems,
like operation deadlock.
So if I have an operation A and another operation B
that is dependent upon the execution of A, this is fine.
However, if I inadvertently make A also dependent on B,
then these two operations will never execute
because they will both be waiting on each other to finish,
and since they are both waiting, they will both never start.
So as you are setting up dependencies
in your application, don't do this.
Now, the WWDC app uses dependencies all over the place.
And a really simple example is what happens when you tap the
"add to favorites" button on a session in the app,
which hopefully you all did for this session.
When you tap that button,
we're going to first create an operation called the
This is an operation that guarantees that you have logged
into the app with your developer name and password.
Next, we are going to create another operation called the
User Info operation.
This is an operation that guarantees that the user name
and password are actually a developer username and password
and not, for example, your iTunes username and password.
So your Apple ID is an appropriate developer Apple ID.
Now, favorites in the WWDC app are stored in CloudKit,
so we also need another operation to make sure
that we have access to your iCloud account.
So this happens silently,
because we are not requesting permission
to see your first name and last name in the app,
so we need to make sure that you have an iCloud account.
And finally, we can set up the save favorite operation,
and this is dependent on the successful completion
of verifying that you are a developer
and the successful completion of verifying
that you have an iCloud account.
So that's a simple example.
Let's take a look at a bit more complex one.
When the WWDC app starts up, there's a bunch
of setup that we need to do.
First, we are going to download a small configuration file,
and this file will tell us small things
like what's the most recently supported version
of the application,
what features we have enabled, and so on.
So after we download this file, we are going
to perform a version check to make sure
that you are running the latest version of the WWDC app.
And then after we check the version of the app,
we can start downloading useful pieces of information,
such as the news that we show in the News tab
and the schedule for the conference.
After we've downloaded the schedule,
then we can start importing any favorites that you've saved
to iCloud, any feedback that you've submitted
so you can see it in the app, and we are also going
to start downloading the list of videos.
All of these things require the schedule to first be in place.
And then finally, we can save our NSManaged object context,
where we are saving all of this information.
So let's see how dependencies
and operation lifecycle affect the execution
of these operations.
And we are going to move them all
into the Pending Operations state.
Now, the first operation
to download the app settings has no dependencies,
so it immediately becomes ready to execute.
And so our operation queue is going to pull it off,
execute it, and then it's going to finish.
Now, when it finishes,
the version check operation also immediately becomes ready
to execute, and so it's going
to get pulled off the queue and executed.
When it finishes, the next three operations simultaneously become
ready to execute.
So they're going to start executing.
And as they finish executing,
more and more operations will become ready to execute.
They will be pulled off the queue and executed.
Now, the important thing to realize here and to notice is
that this final operation
to save our context does not become ready to execute
until everything else has already finished.
By using dependencies, we can guarantee that things happen
in the correct order and that nothing will get out of order.
So now that this one is ready,
it can be executed, and it can finish.
And App Start-up can continue.
So that's a look at dependencies.
Overall, NSOperations are a fantastic way
to abstract logic in your code.
By putting our logic inside of operations, it makes it easier
to simplify these logic changes because we are dealing
with isolated pieces of work, much like we do
when we are dealing with a block.
As an example of this, the WWDC app this year moved
from being -- from saving your favorites and feedback
on a custom backend, to being on CloudKit.
Now, at this point I want you all to think about,
what would it take to move your application from a custom,
from whatever service you are using now to CloudKit?
And if you are suddenly panicking, and all of the places
in your code where you've got network communication,
and all these dependencies on, you know, the intricacies
of your server provider, then this is a good sign
that you should be using operations.
In the WWDC app, all
of our network communication is hidden behind operations,
which means that in order to change the backend
from using a custom service to using CloudKit,
all we had to do was rewrite four small classes.
It took us less than a day and then a couple more days
to successfully test our changes.
It was a simple, trivial change.
Now, in all of this, you might be wondering, well,
what about Grand Central Dispatch?
Grand Central Dispatch absolutely has its place.
In fact, when you download the sample code
for this presentation and look through it, you will see places
where we are using Grand Central Dispatch in that sample code
for things that are not really appropriate to NSOperations.
So for example, anytime you simply need
to bounce a method call from one queue to another queue,
you don't need to wrap that in an operation.
That's something you want to keep fast and very lightweight.
Or if you are doing anything with semaphores
or dispatch group, these are all perfect use cases
for Grand Central Dispatch.
So that's a look at the basics.
Let's go beyond them.
Now, one of the things that we realized in the WWDC app is
that there are places where we want to have UI interaction
but still have it participate in the operation chain.
So for example, authentication.
We talked earlier about saving a favorite.
We need to make sure that you are logged in.
But what if you are not?
Well, we realized that we can put UI elements,
UI functionality within our operations.
So for example, the authentication dialogue
that slides up in the WWDC app is actually an NSOperation.
Or anytime that you are watching a video in the WWDC app,
we encapsulated this inside a "watch video" operation.
So all we need to do is create one of these operations
with the appropriate video asset and put it
on our operation queue,
and everything else will just fall into place.
Even more broadly, any time you see an alert in the WWDC app,
this is something that we thought was also a really good
use case for putting UI inside an NSOperation.
And we discovered that the underlying principle we found
here was that when we're dealing with any sort of modal UI,
so a UI that takes over generally the entire real estate
of your application, this is an excellent thing
to encapsulate inside of an NSOperation.
So to reiterate, the first time you launch the WWDC app,
you saw this dialogue asking
if we could collect some simple usage data
on how you are using the app.
This dialogue that appears, this UI alert controller,
is actually being run from inside an NSOperation.
Or the login sheet.
If you try to add something to Favorites or leave feedback
on a session, this is also an NSOperation.
The next thing we encountered is
that there are some times we want to perform simple pieces
of logic as a block, but we also wanted
to participate inside the operation mechanism.
So we turned to block operations, NSBlock operation
and other custom operations that we created.
So this is really just an NSOperation to execute a block.
And you may be asking, well,
if NSOperation is just an abstraction around a block,
why would I then return to using blocks inside an NSOperation?
And that's because by putting a block inside an NSOperation,
you gain all of the great features of NSOperation
for that block that you do
for NSOperation, such as dependencies.
Let's take a look at what we can do with this
and see what happens when you tap the Leave Feedback button
in the WWDC app.
Well, the Leave Feedback button wants to perform a segue.
It wants to present the view controller
where you can leave some five-star ratings or maybe four
if they were really good but not truly excellent.
We want to perform this segue.
So we are going to put this segue inside of a block,
and then we are going
to put this block inside of a block operation.
Now, we only want to allow you to leave feedback
if you've signed into the app.
So we need to verify that you've signed
in with your developer account, just like we do
when you save a favorite.
And in order to verify that you have a developer account,
we need to make sure that you are logged in at all.
So by putting the perform segue call inside
of a block operation, we can guarantee
that we will never present the login sheet
until after you have logged in.
This is really powerful.
We have described a really complex behavior,
a sequence of things that must occur simply
by using operations and dependencies.
Now, as we were writing the WWDC app,
we noticed that there were some cases where we were doing a lot
of the same operations over and over again.
So for example, we've already seen this login
and user info operation a couple of times.
So we thought wouldn't it be great if there were a way
where we could just automatically have those
So we came up with a way for an operation
to generate its own dependencies.
In other words, we're expressing the idea that we never want
to execute this thing without always executing this
So again, let's take a look at saving a favorite to CloudKit,
or perhaps downloading a pass, or really,
anything in the WWDC app that requires you to be logged in.
So when you tap the "add to favorites" button,
all we are really doing is creating a single operation
to save the favorite.
And this is going to encapsulate some small pieces
of information, the session identifier and whether
or not you want it added to favorites or removed
from favorites, a little Boolean flag.
Now, this "save favorite" operation knows
that it requires permission to run,
so it is automatically going to generate two dependencies,
the one to check that you are a developer and the other
to guarantee that we have access to your iCloud account.
Now, the operation to guarantee
that you are a developer itself needs to guarantee
that you are logged in, so it generates its own dependency
to make sure you are logged in.
And so we are able to keep our app code quite simple.
We only need to create a single operation,
and then it automatically generates its own dependencies.
And perhaps later, if we decide to remove the requirement
that you need to be logged in to save a favorite,
then we simply remove the small line of code
that instructs this favorite operation to generate
that particular dependency, and we have now removed
that requirement across the entire application.
We don't have to go through every single place
where we have an "add to favorite" button
and modify code there.
Now, we also wanted to make sure that other kinds
of conditions were met.
We wanted to be able to expand upon this idea of readiness,
expand upon the idea of when we're allowed
to execute an operation.
Some examples that we came up with include, we only want
to execute this operation
if you are actually connected to the network.
If you try to add the favorite in while your phone is
in airplane mode, for example, we, of course,
don't want to try executing our CloudKit operation.
We also want to guarantee, perhaps, that maybe we only want
to execute an operation if we have access to your location.
So we need a way to express this as well.
Or for example, we only want to execute certain kinds
of operations if you are actually logged into the app.
So by extending the concept of what it means for an operation
to be ready, we can make our operations even more powerful.
So hopefully you won't ever see this error, but if you do,
this is an example of an operation failing
because it was never able to become fully ready to execute.
In this case because it was unable
to connect to the network.
So extending the readiness concept can also be
Next, there were a couple of operations where we found
that they were always being done together.
So we thought, wouldn't it be neat if instead of having
to create the same sequence of operations over and over again,
if we could just create one operation and then
under the hood it would create the same sequence
of operations for us?
A common example of this is the idea of downloading something
and then parsing it to save into a local storage.
I am sure this is a concept that almost all
of you are familiar with.
So let's take a look at how we can compose operations
to make them simpler.
So let's say we have a generic import data operation,
and then it's dependent on something
and other things are dependent on it.
We have this import idea.
Well, we want this to actually do two things, so it's going
to wrap another NSOperation, and this operation is simply going
to perform the download.
It's a single, isolated piece of work.
And then it's going to create a second operation
to parse whatever was downloaded and make it dependent
on the download operation
so that parsing will always occur after downloading.
Now, by encapsulating those two operations inside
of a larger operation, we can now easily change perhaps,
maybe where our data is coming from, what format it's in,
and even how we handle errors.
And we only have to do this in one place,
inside our import operation, because that's the only thing
that the rest of our app knows about.
Now, you don't always know ahead of time, perhaps,
the exact operations that you need to perform.
In the WWDC app, we cannot know
at compile time how many favorites you've saved
to CloudKit, so we needed a way to be able
to dynamically compose operations.
So we created this wrapper called a Fetch Favorites
operation, and since we are using CloudKit,
under the hood we are going to perform a CK query operation,
because CloudKit is also built on NSOperation.
So we are going to perform our first query operation.
And maybe you have every single session favorited at WWDC,
so this is going to indicate
that there are still more favorites to fetch.
So we are going to keep on executing query operations
until we have received a response that that's all of them
and we've got them all.
So by using this composition model,
we can still simply express our operation chain as a single --
with a single "fetch favorites" operation, but under the hood,
actually be performing many operations,
potentially, in sequence.
Now, in the code, it looks something like this.
Our operations have an execute method,
and this is where they all start doing their work.
So the first time the fetch favorite operation starts
executing, it's going to set up the initial query.
We are going to look for session favorite records created by you.
So we are going to construct our query operation and pass it
to this method called execute query operation.
And this is the execute query operation.
As this query operation completes, we are going
to first check, was there an error, and if there was,
let's abort the process and handle the error.
If there wasn't an error, but instead, there was a cursor,
this is how CloudKit tells us
that there are still more things for us to fetch.
So we're going to create the next CK query operation
in the sequence using this cursor
and semi-recursively call this execute query operation.
And this is how we can be executing many query operations.
And then if we get neither the cursor nor the error,
this is how CloudKit indicates that we have fetched everything,
and so we can begin to import the records
that we have downloaded.
Next, during development, there were some times when we came
up with some visual glitches,
the things that we thought were visual glitches.
Now, perhaps you've all had the experience of using an app
and an alert pops up, and then as you are
about to tap the button, another alert pops up.
And you think, oh, great, man, what is even going on now?
And as you are about to tap that button,
maybe another alert pops up, and with all of the animations
of coming and going, you are no longer even sure if you are back
on the first alert or if you are now on the third.
We really wanted to avoid this confusing scenario.
Another thing we wanted to do is we wanted to guarantee
that you could never, ever try to watch more
than one video at once.
This is something that the WWDC app does not know how
to handle correctly, so we wanted to guarantee
that no matter what you did,
we would never allow you to do that.
Another thing we wanted to guarantee is
that we would never try to load our underlying database more
So we came up with a way of describing mutual exclusivity,
the idea that only one of these particular kind
of operations can be running at a time.
Now, you are probably thinking, wow,
this is a really complex idea.
How would we even do this?
And it is really simple.
So let's go back to the alert example.
Let's say we create an operation to display alert and alert
to the user, and we put it onto an operation queue.
And maybe it's there waiting for something else to finish,
maybe it's already in the middle of executing.
But then something happens, and we decide
to create another alert operation.
Well, all we need to do is make the second alert operation
dependent on the first one.
And this is where cross-queue dependencies are
Because it does not matter
which queue this alert operation is executing on,
as long as the second operation is dependent on the first,
then the second operation will never execute
until after the first operation completes.
And so for some -- if for some insane reason,
we decide to create more alert operations,
even more alert operations, as long as we set
up these dependencies of the next operation being dependent
on the previous, like a singly linked list back in time,
we are guaranteeing that our operations will be
This is really powerful.
By using dependencies,
we can guarantee correct behavior in our application.
We can guarantee that you will never see more
than one alert at once.
We can guarantee that you will never be able to watch more
than one video at a time.
We can guarantee that we will never try to load two copies
of our data store simultaneously.
So those are a taste of some of the challenges that we came
up with when writing the WWDC app.
There are more.
But we think these ones are really cool.
And we came up with what we thought was a pretty neat way
to solve them.
So let's talk about the sample code.
On the WWDC website, under the sample code section,
you can find a piece of sample code called
And this is a simple app to show recent earthquakes.
But under the hood, it's built entirely on NSOperations,
and the operations that it's using in the app is code
that we have extracted from the WWDC app
and put into the sample.
And this is code that's been in the app, actually,
for a couple of years.
It is stable.
Now, the primary class that this sample code uses is operation.
And this is a basic subclass of NSOperation.
And in the sample code, this operation adds two key features.
The first is the idea of a condition,
which we will talk about in a second.
And the second is a concept that we call "observers."
Now, we've got a bunch of different kinds
of operations in the sample code.
We have group operations, so it's very easy
to make operations internally perform more operations.
We also have an operation subclass in the sample code
that allows you to take an NSURLSession task and wrap it
up inside of an NSOperation so that you can make it, perhaps,
dependent on something else or make other things dependent
on this, or perhaps add conditions or observers to it.
There's a simple operation to request your current location.
There's one -- because it's sometimes useful --
to just simply wait a little bit of time.
There's even an operation to show an alert to the user
with buttons and block handlers.
So lots of great kinds
of NSOperation subclasses in the sample code.
Now, this operation has a concept of a condition.
And a condition is a protocol that we have defined,
and it's a way for an operation
to express how it generates dependencies,
how it defines mutual exclusivity,
and also how it extends the concept of readiness.
So some kind of conditions
that we have provided in the sample code.
One is the mutually exclusive generic condition,
and this is a way of describing
that an operation is mutually exclusive with other kinds
of operations with the same generic type.
We have a reachability condition in there, so you can simply,
with one line of code, express
that an operation can only execute
if the network is reachable at a very high level.
And we've got a plethora of permission conditions,
such as only execute this operation if we have access
to a certain CloudKit container, or only execute this operation
if we have access to your calendar
or to your photo library or to your contacts
or whatever else you'd like.
So that's conditions.
And the final piece is operation observers.
An operation observer is again a protocol type, and it's a way
for this value to be notified about significant events
in operation lifecycle, such as start or the beginning
of execution, the end of execution,
and also if the operation decides
to produce another operation that should be executed later,
such as if an operation decides that it failed and it wants
to show an alert, it can produce or generate an alert operation.
And we have a couple of examples of observers, such as timeouts.
By simply adding a timeout observer to an operation,
that observer is going to watch to make sure
that the operation completes
within whatever time interval you specified,
and if it takes too long,
it's going to automatically cancel it.
One that I think is really neat is a background observer,
so this is an observer that when you attach it to one
of these operations is going to watch the state
of your UI application,
and if your application enters the background,
it's going to automatically begin a background task,
and then automatically end it
when the operation finishes executing.
So if you have some sort of critical operation,
perhaps you are uploading data to a server and you don't want
that to be interrupted or suspended,
one way you can accomplish this is by adding one
of these background observers to the operation,
and it will guarantee that you have some time
in the background during which you can complete this operation.
And another one that's really cool is the network activity
This is a simple observer you can attach to an operation,
and when it begins, it's going to increment a sort
of retain count on the activity indicator spinner
in the status bar, and then when the operation ends,
it's going to decrement that retain count.
So you can have multiple networking operations in flight
at the same time, and by simply attaching one
of these network indicator -- or, observers --
it will automatically show
and hide the network activity indicator as appropriate.
It is no longer this crazy --
crazy state that you have to manage yourself.
It all kind of happens automatically.
It's really cool.
And then there are other observers that we have
in the sample code for you, such as being able
to attach arbitrary blocks to one of those three events
and have them react appropriately.
So that's a quick look at the sample code.
On the surface, it looks like a really simple application,
but under the hood, there is lots of really meaty goodness,
and I really encourage you to download it and check it out.
So, in summary, use operations
to abstract the logic in your app.
By putting your logic inside of operations, it becomes very easy
to change it later, such as how we converted the WWDC app
to use CloudKit.
It was a simple change for us.
Use dependencies to express the relationships
between your operations.
It makes it very simple to guarantee certain kinds
of behaviors, that B must always follow A.
Next, operations allow you to describe complex behaviors,
such as mutual exclusivity or composition.
These are all simple with operations.
And overall NSOperation allows you
to perform some very powerful things with very minimal effort.
So we have a couple of related sessions for you.
Immediately after this session is "Building Responsive
and Efficient Apps with GCD."
We don't want you to leave GCD behind.
It is still a perfectly appropriate technology to use.
So I encourage you to go to this session or watch the video
and see when you should be using GCD in your apps.
And then if you want to see more
about how our frameworks use NSOperation, you can watch the
"CloudKit Tips and Tricks" session from this year
or the "Advanced CloudKit" session from last year.
Like I said, we have sample code available on the WWDC website.
I encourage you to check it out.
I also want you to read the 'Threading Programming Guide'
in the Developer Library.
This has a lot of really great information on other ways
that you can use NSOperation.
And if you need any technical support, we encourage you
to post your questions in the Developer Forums or contact DTS.
Thank you very much, and have a great rest of the conference.
Looking for something specific? Enter a topic above and jump straight to the good stuff.
An error occurred when submitting your query. Please check your Internet connection and try again.