WWDC2010 Session 105

Transcript

>> David Myszewski: Welcome to the multitasking talk.
I'm David Myszewski and I manage
one of the iPhone performance teams.
I've been working on performance for
about four years and we're going to talk
to you all about multitasking in today's talk.
Also joining me will be David Goodwin, who is an
engineer on my team and spent a lot of time thinking
about multitasking for the last, last year or so.
So, to give you a little, brief
introduction into multitasking,
multitasking is of course a really,
really huge feature of iPhone, of iOS 4.
It's one that we hope that all of you will
adopt in your applications and in fact,
in order to best have the user experience on the iPhone,
we expect really all the apps on the
App Store to adopt multitasking.
And this is part one of a two part series and we'll
talk a little bit about what that means in a little bit.
Now of course, multitasking dramatically
improves the user experience.
Switching back and forth between apps
is really, really seamless on iOS 4.
And applications that you have are just that much better.
Because the user can return immediately to where
they were and they don't have to wait at all.
So it's often the case that your application
will be just sitting around in the background
and the user comes right back to your
application and it's right where you left it.
So it makes existing apps just that much better.
And in addition to that, we're enabling a whole new
category of applications that couldn't have been written
on previous OSs and this will make the
overall user experience a lot better on iOS.
And as I said, every single application
on the store should adopt multitasking.
And today, in this particular talk,
we're going to focus on the features
that we think everybody who's developing
applications for iOS 4, should take advantage of.
So today you'll learn a few things.
First of all, we'll give you an overview about what
multitasking means on iOS 4 and then of course,
we'll describe to you how to enable
multitasking in your application.
And that's going to be a combination of things.
We have provided a bunch of fantastic APIs for you to
adopt and we'll talk to you about what the workflow
of those APIs is, as well as how your application can
fit in really well with the rest of the operating system.
So we'll have some responsibilities
and best practices that we'll discuss
so that your application can be
that much better on the iPhone.
And then finally, we'll describe to you a little
bit about some development tools that allow you
to more easily adopt multitasking and
figure out what your application is doing.
So, to start things off, David Goodwin is
going to give us a little bit of a demo.
>> David Goodwin: Good morning everyone.
[ applause ]
So, here we have two iPhones, 3GSs.
One has iOS 4 on it and one has iPhone OS 3.
You can probably tell which is which.
What we are going to show today, just a brief overview of
what multitasking can do for every single app out there.
Every single app on the App Store.
So first let's, what we have for a
demo here is a pretty simple app.
It's just a little journaling app, that you can like
make little notes in and attach a little photo to
and I'm going to launch that on each device.
And here it launches up.
You can see we have our entries for just a
few things that I've been journaling about.
Then we can look into them.
Like there's this little kayak trip.
That was pretty nice.
OK, oh I did notice back there
actually though, this Irwin's wedding.
I was, I see that I'm thinking oh, I had
some other photos about Irwin's wedding.
Wouldn't it be great, I want to
go check those out right now.
That just reminded me.
Well, iPhone OS 3 of course, we would
return to SpringBoard and we'd find photos
and we'd launch it and go into the wedding.
In iPhone OS4 of course, we have
the great, new multitasking UI.
So I can just double-tap that.
Photos, which it turns out, one thing you'll notice
here, not only did I switch quickly into photos,
but I had been looking at photos earlier.
Maybe a couple days ago, maybe even a week ago.
I don't know.
It could have been running in the
background for a long time.
But right there it is.
I can quickly get to that, my photo library.
In this case I want to look at some of
Irwin and Jill's photos from that wedding.
And now I want to, OK but I want to go back to my journal.
Again, iPhone OS 3 you leave the photos app
and find journal here again and launch it,
iPhone OS4 I'm going to use this great
multitasking UI and I'm going to go right back.
Now one thing I noticed here is, I didn't do the best
job I could have writing this application, did I?
Because when I returned on iPhone OS
3 and I relaunched the journal app,
actually didn't bring the user
right back to where they were.
Now that's my mistake as a developer.
I could have done a better job.
But on iOS 4, we help you out a little bit there
and we actually came right back to that same spot.
Now, let's look, another interesting thing here, let's,
this hike at Lake Tahoe, it has a little, a URL in it.
My journal app let's you put URLs in.
And I can again, I can follow an URL link in each of these.
And again, I switch right into Safari there, with the UI.
Whoops, well I didn't go Wi-Fi.
We don't have any Wi-Fi problems I hope.
And again, once again, following URLs or switching
quickly between apps, it's much quicker, much easier,
much better user experience for all your
applications in iOS 4, compared to iPhone OS 3.
And so hopefully that demonstration there
helped you see why, how compelling it will be
for you to adopt multitasking for your app.
Now back to Dave.
>> Dave Myszewski: So, we have a particular view
on multitasking for iOS 4 and in particular,
we don't believe that general purpose
concurrency is the solution for mobile devices.
Mobile devices have limited resources.
They have limited CPU, they have limited RAM and so
we think that in the application that you just saw,
that really the important thing for that application wasn't
that the app was actually doing something in the background,
the really important thing was that when the
user returned to the app, the state was preserved
and the user could immediately interact with the app.
And for all of the applications on the App
Store, we believe that that will be true.
That you really want to be able to quickly switch to
particular applications and return to exactly where you were
and be able to immediately interact with the app.
And so in fact, that's, if you look at a pie
chart, that would be our pie chart, 100%.
But you know, there are obviously some applications
that boy, you really need to run in the background
in order to accomplish the particular task.
And so what we've done with multitasking is we've created
a little slice of the pie that applications that benefit
from background execution and we
have enabled certain categories
of applications to continue running into the background.
And these ones will be described in great
detail in the second talk and in particular,
the ability to finish some task that you
are in the middle of, play background audio
and do some location in VoIP, also in the background.
So, with multitasking we've provided a solution that works
very well for all developers, for quickly switching back
and forth between applications and then also
enabled some new categories of applications.
Now of course, we still have push notifications, which are
a fantastic way for the server to do all the heavy lifting
and the processing and the pulling, the things that
would consume battery life and then send a notification
to the device when some interesting data
that the user should know about, arrives.
So push notifications still are a fantastic
tool to use, even in the multitasking world.
Because we are pushing all of the heavy lifting
for CPU and battery life, onto the servers.
So as you saw, we have a lot of benefits
for what we're calling fast app switching,
which is that the application resumes really quickly,
all of the state was preserved exactly where you left it.
We provide some great APIs to integrate really
well with the multitasking UI and of course,
all of the apps on the App Store, we think
will update to this and so, you know,
the whole OS just behaves better if
everybody has adopted multitasking.
So I'll give you a brief overview of the services.
The one that we're going to focus on for this
particular talk is what we call, fast app switching.
The ability that you saw to resume
quickly and preserve state.
Push notifications, of course, are still relevant
in the multitasking world, as I just described.
Local notifications, which are a nice tool in which
you can provide the services of push notifications,
so displaying an alert, badging your icon, playing a sound
at a predetermined time and then a few different services
for which applications can take advantage of that
will be described in great detail in the second talk,
which are background audio, so the ability to play audio
in the background, as you saw in the keynote yesterday.
Task completion, which basically it recognizes that there
is a category of apps for which the user initiated a task
in the foreground, like uploading a photo or downloading
some content and you really want that operation
to complete before, without the user having
to keep the application in the background.
So we're calling that task completion, the ability
to complete a specific task in the background.
And we have a couple of location services.
One that's focused on navigation, which allows
you to use GPS in the background and give very,
very precise notifications of location changes and some new
services, which we're calling significant location changes
and region monitoring, which are low power abilities to
figure out when the location changes in the background.
And then the last one is Voice Over IP, which allows
you to both continue while on the call in the background
and of course receive calls in the background.
So together, all of these services
comprise our multitasking solution.
And as I said, we're going to focus
on fast app switching in this talk.
In the second talk, we'll go through all of those services
in that second slide that we were just looking at.
So, if you're a developer, how do you enable multitasking?
Well it's really simple.
Just build with the iPhone SDK4.
Fast app switching is enabled by default and
so we think that every app should adopt it
and so we made it the default behavior
when you compile with iPhone SDK4.
And of course, if you have some of the other
services like background audio, location and VoIP,
then we require that you have an explicit
declaration in the apps Info.plist.
So, your app lifecycle changes a lot with
multitasking, so to describe in very great detail
about how the app lifecycle behaves
in this new multitasking world,
David Goodwin is going to come back on
stage and describe how it all works.
>> David Goodwin: So, iOS 4 give us
these great multitasking services.
As Dave said, today we're going to focus mostly on
fast app switching, although a lot of what we'll talk
about as well will be kind of general things.
Responsibilities, best practices, that you need
to be aware of when you're writing your app.
Before we go into those responsibilities and best practices,
we're going to go into detailed
walk about how your app behaves.
Now you might know this from your iPhone OS 3
development, in fact we're going to review that first
and then go into the detail of the iOS 4.
You know, how your application
acts, how the user interacts with it
and how your application interacts with this lifecycle.
So let's start again.
We'll start with the review of iPhone OS 3.
Now iPhone OS 3 basically has three
states that your application can be in.
The not running state, which is pretty obvious.
And then two running states, inactive and active.
So let's review how when the user interacts with the device,
how your application transitions between these states.
Again, initially your application
is in the not running state.
User launches your application.
As an example we'll use Maps in this case.
Map starts running.
Your application transitions through an inactive
state and then into the active running state.
So this is the normal foreground running state.
Your app's in the foreground, the user can interact with it.
But what can also happen while your app is in the foreground
is for example, you can receive an SMS or some other alert,
push notification, incoming phone call or the user
can lock the device over top of your application.
In all those cases what happens is, your
application moves into the inactive state.
Now your application is still running, it's still
in the foreground, but it's kind of obscured
or there's something else on top of it,
that puts it into this inactive state.
Now from the inactive state, the user can take some
action to move it either back into the active state
or potentially into the not running state.
For example with an SMS, if the user choose to
reply to the SMS, the SMS app is going to launch
and your application would go into the not running state.
In this case, let's assume the user pushes the Close
button, so he's not going to look at the SMS right now.
That returns your application back into the active state.
And of course, the last thing a user can do is to
leave your application by hitting the Home button.
In that case, your application
transitions into the not running state.
So again, this is very familiar.
This is the way your applications have been
interacting with the user and
with the application lifecycle in iPhone
OS 3 and so let's compare that with iOS 4.
We'll start with the familiar states we just talked about
and in fact the device mostly behaves
the same way with respect to those.
So your application is not running.
The user launches it.
Again, we're using Maps.
Moves into the active state.
Now, as before there's an inactive state that your
app can enter and that's the same as in iPhone OS 3
or an SMS, incoming phone call, et cetera.
There's a new inactive, a new way to enter into the
inactive state and that's through the multitasking UI.
So if the user brings up the multitasking UI, your
application will again enter the inactive state.
If they dismiss the multitasking UI or any
of those other SMS, just like in iPhone OS 3,
your application will return to the active state.
Now, together, because your app is in the foreground,
you know it is running, we group together the active
and the inactive states together,
as the foreground execution state.
Of course, the exciting new thing, most exciting new thing
about this application lifecycle with regard to iOS 4,
is that we're going to introduce two new background states.
And these are, we're calling them the background
running and the background suspended states.
The background running state, as you
can imagine, is when your application is
in the background, but is allowed to continue running.
Now as Dave mentioned, there's some services, some
categories of multitasking that where it's beneficial
to allow your application to continue running and those
applications then would be in the background running state.
This background suspended state, is the state that the
system uses, when it really wants to minimize the impact
that your application has on the entire system as a whole.
So your application is not terminated, it moves into
the suspended state where it reduces your system use,
resource usage and remains in the background.
And this is the one which we'll talk about a
lot more with regards to fast app switching.
So, let's say the user there had
the Maps app was in the front
and now they hit the Home button in iOS 4, to dismiss that.
So unlike iOS 3, they're not terminating the
application anymore, what are they doing?
Well instead the application moves into the background.
Now all applications will be in the background running
state, even if it's temporary and we're going to talk
about more of this in a minute, and from the background
running state the system may move your application
into the background suspended state.
Now, here's a difference, another
difference from the iPhone OS 3 lifecycle,
whereas before when your application
would terminate from either the active
or the inactive state and move into the not running state.
In iOS 4, your application moves into the not running state,
from either the background running
or the background suspended states.
And we're going to talk in more detail
in just a minute about how that happens.
OK, so what we just described is, the user is
interacting with the phone, they're launching,
they're using multitasking UI,
they're returning to SpringBoard
and we saw how those user actions effected your application.
How it moved it through its lifecycle.
Well, so but as the application developer, how are you
going to be aware of these lifecycle changes and respond
to these lifecycle changes and take
the necessary actions that you need to?
Well just like an iPhone OS 3, we have UI
application delegate callbacks and notifications,
which are used to inform your application
of these transitions.
So let's walk through them and
we'll start with the familiar ones.
Again which are more or less identical
to what you have in iPhone OS 3.
So you're in the not running state again.
We're going to use Maps as our example again.
The user launches it and what happens?
Your application receives, the application did
finish launching with options, delegate callback,
as an indication that the application is being launched.
Transitions briefly into the inactive state.
Continues the launching process, your application
will receive, application did become active.
At which time now it is transitioned completely into
the active state of the foreground active running task.
Let's say again that some interruption occurs like
the multitasking UI or something else that causes it
to transition into the inactive state and of course
you'll receive, just like today, you'll receive,
the application will resign active callback.
OK, so that's all very familiar to
us, let's look at something new.
So again, here's your application Maps that's
running in the foreground, user hits the Home button.
So you're in the active state, they hit
the Home button, the application now moves
through into the inactive state again temporarily.
You get, your application will resign
active callback, followed by a new callback,
new for iOS 4, called applicationDidEnterBackground.
This is an important callback, as you
can see from our lifecycle diagram.
This is the indication to your application that it's
moving from a foreground state into the background.
Now we're going to talk, we're going to talk about
responsibilities and best practices here in a few minutes,
you're going to see that this is a very
important point in your application's lifecycle.
This is the point where you would save application state for
example, try to reduce your memory usage and other things,
other responsibilities which we're
going to talk about later.
So now, as I said, your application after it's moved
into the background running state and depending
on which services your application benefits from,
it could remain in this background running state.
However, for a fast app switching application, the
transition is going to continue and the system is going
to move it into the background suspended state.
Now this box is empty.
This is a very important point of your application's
lifecycle is that your application and the user
for that matter, is not going to have any
indication of when the application transitioned
from the background running state
into the background suspended state.
And the implications of this, there's going to be
implications of this about when you need to reduce memory,
when you need to save your state, which again we're
going to talk about in the responsibilities section.
So let's do the other way around here.
If your application is, it's running,
so it was launched earlier.
It's in the background in the suspended state and now
the user reselects the icon or selects it from the,
from SpringBoard or from the multitasking
UI, basically launches it again, resumes it,
we have kind of the reverse set of steps.
Again, the system is going to first move your
application into the background running state.
There's not going to be any indication to
you or to the user that this is happening.
You as the application developer, your application.
You're going to receive a new, another
new ApplicationDelegate callback,
applicationWillEnterForeground, again a very important
callback, because this is the indication to your application
that the, that the app itself is transitioning
from the background into the foreground.
Briefly through the inactive state and then back into
the active state with applicationDidBecomeActive.
So then we saw how we transitioned,
the normal transitions for launching.
We saw the transitions into the
foreground, into the background.
So what about termination?
The user doesn't terminate your application every
time they hit the Home button anymore, obviously.
So what, but there is still a not running state in iOS 4.
Your applications don't run indefinitely.
So, one way that the user or the way that the user can
move your application from the background running state
into the suspended state or into the not
running state, is through the multitasking UI.
So in this case let's assume that we have iPod
actually running and playing audio at this point.
So it's actually in the background running state.
Using the background audio service to play its audio.
And the user uses the little minus
sign there to stop, to terminate iPod.
Well the transition into the not running state
and this delegate callback you're familiar with,
this is the applicationWillTerminateDelegate
callback that you had today,
it's just occurring at a different point in the lifecycle.
Well let's look at another background state.
So we also have Maps down here.
Now Maps, Maps does not have any benefit from running
in the background, so it actually is suspended
by the system when it's in the background.
So it's sitting there in the background suspended state.
But what if the user you know,
closes it now with the minus sign?
Well here's another case of that, the system will transition
Maps into the not running state, it will terminate Maps,
but there's not going to be any indication
to Maps that it just got terminated.
So again, this has implications in that once
your application enters the suspended state,
it had better have done all the cleanup, all the
saving, all the bookkeeping that it needs to have done.
Because once it's entered the suspended state,
it can be moved into the not running state,
without ever getting the chance to execute any code again.
So that's a very important principle that's going to
guide some of our best practices and responsibilities.
Now as I mentioned, this is a little bit of an eye chart.
But you have these UI applicationDelegate callbacks,
along with each one there's a corresponding notification
and so for the two new delegate callbacks, we've
added two new notifications for the foreground
and background transitions and you can
look these up in the documentation.
The way that you use these notifications
is identical to how you did in iPhone OS 3.
OK, so I've eluded a lot to responsibilities
and best practices and so,
we're going to start talking about those now.
It's important to keep in mind that a lot of these are
phrased, although we're focusing on fast app switching
in this talk, with the lifecycle I just
talked about and all these responsibilities
and best practices, apply to all multitasking applications.
Now there might be slight variations that we'll talk
about, so if your background audio app or a VoIP app,
that the second talk will cover any
exceptions or details that you need to know.
But in general, what we're going to talk about here applies
to all multitasking apps, not just fast app switching.
So, before we get to the details, let's talk
a little about system resource management.
So, of course a big goal at Apple, with our
multitasking implementation and as Dave eluded to before,
we think that a kind of general purpose
concurrency, general purpose background execution,
that's not appropriate for these type of mobile devices.
Because we really want to do two things.
We want to preserve battery life, obviously and
you know, in the keynote there was a great quote
from Sergei, I think, about how
just having these background tasks running wild,
running free in the background, that's not
good for the battery and we agree 100%.
The other big thing is those background, free running
kind of background tasks, Wild West background tasks,
it's not good for the device's usability.
Its responsiveness.
And so those are our two goals with some of these
responsibilities and best practices and indeed,
the general design of the multitasking as a whole.
And of course the system resources are
shared by all the apps and that goes
without saying and there are limited resources.
And so, you should really try, when you're thinking
about your app that's running in the background
or even if it's going to be suspended in the background,
you need to think about minimizing your resource usage.
And we're going to give you some best practices and point
out some places where you can, you can help out with that.
And this is not completely something that
oh, we want you to do this for the system.
You'll see how that by doing these best practices and
adopting and taking these responsibilities seriously,
you'll make your application work better
in this whole multitasking environment.
You'll, it can be a differentiating factor when people
use your application, they'll notice that oh, when I come,
his application whenever I go back
to it, it's right where I left it.
And we'll see how you can do that.
So here's an outline of the thing.
So I've kind of grouped them into two categories.
Some responsibilities and best practices
for when your application is making
that transition from the foreground into the background.
And we'll go through these in detail.
And then there's a kind of corresponding set, shorter
but, when your application, it's been in the background
and now the user is bringing it to the foreground again,
there is some things that you need
to take care of and be aware of.
So let's start here.
We'll start with a big one, which
is saving application state.
So, I mentioned earlier that it's important, that once
your application enters the background and it moves
into the suspended state, your application
isn't necessarily going to get another chance
to execute any code before it can be terminated.
And so you know, a big implication of that is that
when your application goes through that transition
into the background, as indicated by the callback or the
notification, you need to save your application state.
Because if your application is terminated,
whatever you saved at that last transition there,
that's what you're going to you know, your app's going to
have when it starts back up again, when it's relaunched.
But that might not be sufficient.
As with all these UI applicationDelegate callbacks and this
is true in iPhone OS 3 as well and it continues to be true
in iOS 4, there's a limited amount of time that your
application can spend in those delegate callbacks.
A few seconds.
And so if you have such a large amount of application state
or other work that would need to be done on this transition
into the background, you know you might not have
time to always save all your state in that time
and that would be a lot of state, but it's something
you need to be aware of and so you might need
to adopt some other state saving strategies as well.
Save part of your state incrementally
or you know, as you go along.
This makes a lot of sense, especially in
something like a turn-by-turn game for example.
It's very natural to save your state
at check points or levels and what not.
OK so that's one responsibility.
Another one is reduced memory usage.
This is also a very important one.
Let's get into this.
So system memory, it's a limited resource on these devices.
And so as such, the system, when
it needs more system memory,
the way it frees up more system memory
is by terminating an application.
So as I showed in those lifecycle diagrams earlier
on, there were transitions from background running
and background suspended into the not running state
and one way to get those transitions to occur is
from the user's action as I showed in the multitasking UI.
Of course another way those transitions can occur
is that the system needs to free up some memory.
The user is launching a new app that they hadn't,
that hadn't been launched, memory is all used up.
Well, you know, this new app's going to need some memory
and so the system it prioritizes how it goes about deciding
which app will be terminated to free up the system
memory needed for by say this newly launched app.
And roughly the prioritization goes something like this.
We have, again we have some apps that are in the
background suspended and some in the background running.
Let's roughly categorize those apps into ones that
are using a lot of memory, a lot of memory usage
and some that are using you know, a small amount of memory.
And the system is going to greatly prefer to
terminate the high memory using applications.
The other point to make here is that this memory,
termination due to a low memory condition,
this is the normal state of the device in iOS 4.
When users leave an app and go into another app,
the app they just left, it's still there in memory.
Now they go to the next app, the next, you know, four,
five, six, ten, all those apps are going to remain in memory
until the system memory resource is exhausted
and the system is required to terminate one.
So, it's an important point that it's a normal condition.
So, now we see that, so your application can be
terminated because of this low memory condition.
So of course, using less memory from a system point of view,
from a usability point of view, from a user happiness point
of view, if all the apps together are doing their best
to use less memory, well the user is going to be able
to have basically a greater working set of
apps that can stay resident on the device,
before the system needs to do any of these terminations.
So, you can think about in your own usage, what's
your working set of apps and wouldn't it be great
if the large working set you know, when I
go back to it, it's right where I left it.
It's been resident in memory you
know, for hours, for days, for weeks.
Now here's the part though, this is again, it's not just
kind of a touchy feely kind of oh we whatever system thing,
it's very important for your individual
app to do this as well.
Because of that prioritization we saw about apps that
use a lot of memory are much more likely to be chosen
for termination than the ones that use low memory, it's in
the interest of your app to reduce its memory usage as much
as possible when it's in the background, so
that the system decides not to pick your app.
And again this comes back to if your app is terminated,
the next time the user goes back to it, well it relaunches
and depending on how good a job you've done about saving
state you know, maybe you just take them right back
to the home screen, maybe you kind of navigate
them down to the appropriate point in the UI
or back to the beginning of the
level they were on or whatever.
But in any, it would still have to relaunch.
And as opposed to an app that didn't get terminated,
when they go back to it it's going
to be exactly where they left it.
It's going to resume very quickly and it's
going to be exactly where the user left it.
And so you want your app to be in that latter category.
You want the you know, you want it to be the last app on
the system that gets terminated, when the system is looking
for an app to terminate for a low memory condition,
you want your app to be the one it chooses last.
And again, because as we saw in the
priorities, the prioritization is only for apps
that are in the background will get terminated.
You know, you need to take care of the stuff we're
going to talk about, about reducing your memory,
you need to take care of that while your
application is entering the background,
which is in the applicationDidEnterBackground callback.
Now we have a great tool in Instruments.
You might have used Instruments for many things before.
It's a great tool for doing a lot of performance type work.
And you can use it also, there's
this tool, this VM Tracker tool,
which you can use to help you first off determine how
much memory you're using when you're in the background
and then as you're working to reduce it, you can you
know, use this tool kind of to measure your progress.
What you're interested in and I've circled
in yellow here, there's a row marked dirty,
then over on the right there's a dirty size.
In this case it's 6.04MB and that's the number, this
is the dirty memory, so this is basically the number
that the system is going to use, when it's looking
at your app, this is the one that's going to say oh,
he's using that much memory and that's what
it's going to use to prioritize your app.
So, again your goal would be, when you're trying
to reduce your memory usage in the background,
is to drive that number down as low as you can.
But there are some trade-offs which
I'll talk about with that
and let's talk a little bit more
generally first about app memory usage.
This is to say, this is the journal
app which I showed earlier.
It could be any application.
Let's just talk generally about
you know, memory usage in an app.
Well you have some App State.
This is app specific state.
You know in the journal it was
images that were those photos,
the entries themselves, the text
and the titles and what not.
You know and those are probably backed by some kind of
store on disk store, that could be, could be using SQLite
or Core Data, you know there's cache or you might have
you know, flat, I'm just going to call it flat file.
Your own custom file format that
you're using to save this data.
Whatever it is, you have some kind of backing store.
Now for your UI, you have views and
layers and those are backed by a store.
The system in order to render those
graphic, render the UI correctly,
it has its own backing store which
it maintains for your views.
And finally you have some kind of controllers,
view controllers, maybe other kinds of controllers,
which kind of ties it altogether,
ties your model together with your UI.
So that's just kind of an abstract
look at memory usage by an application.
Well, when your application is making
this transition into the background,
the system is going to do some things for you.
You know, because we want to really help you
out, again it's beneficial to the entire system,
it's beneficial to your app, the usability of your app,
the happiness of our users, so the system is going to try
to do what it can for you and it can do some things.
So the system is kind of maintaining this backing graphic
store for you and once you move into the background,
you're not going to have, your UI is not going to be
displayed anymore, so the system is going to go ahead
and free that up for you and that
actually saves quite a bit of memory.
If you have views that are not visible, off screen
or whatever, we're going to free those up as well.
That'll save a little bit.
And if you're using the image named cache, the APIs to
manage your images, we're going to flush that as well.
Although there is still a responsibility, you
have to release those images that you are using
from the image named cache, which
we'll talk about in a second.
You know, if you're using SQLite or Core Data, NSCache,
the way those frameworks are implemented
is efficient in its uses of memory.
They have some caching and so as much as we
can, the system is going to flush those caches,
move that data out of memory and
so free up as much as it can.
That being said, so the system can do some
things for you, it can't do everything of course,
so there's going to be some things that
your app is going to need to do for itself.
As I mentioned earlier, release images.
Whether you're using image named APIs or other
image APIs, images can take a large amount of memory
and so it's important, in most cases, in almost all cases,
for you to release your images when
you're going into the background.
Now if you have your own caches, not necessarily the SQLite
or Core Data caches that are maintaining on your behalf,
if you cache some stuff yourself, from your own
file, it's good to flush these caches and again,
there's a little bit of a trade-off here in that you
know, if your caches are very expensive to create
and the reason you have those caches is because they're
very expensive and you don't and if you flush them,
then when the app comes back to the foreground,
you're going to have to regenerate them all again.
Well so here's the trade-off you know.
How much memory are you going to save versus
how long is it going to take on resume
to regenerate this data and that's,
that's an app by app call.
But it's something you should at least consider.
And the other things is, for this flat
file, if your backing store is a flat file,
not using some of these other technologies, you should
consider instead of saying f open it or opening it
and reading the whole thing into your, into your
app's address space and using it and you know,
when you modify things or save
state you write the whole thing out.
That can be much less efficient than using some of the
memory mapping technologies through the mmap family of APIs.
So especially if you're doing a lot of read
only access, but even if you're writing,
the system can be much more intelligent about which
parts of your flat file are moved into memory,
it can move some parts you know, back out of memory as
necessary, without requiring termination of your app.
So again, something to consider if using a custom file
format as your backing store for your application state,
you know to consider if memory
mapping would be appropriate for that.
Because there are some benefits that
the system can provide for that.
So I mentioned a couple times about
trade-offs and other, so there's trade-offs
and there's other small memory usages in your application.
So a trade-off, we haven't mentioned view controllers yet.
Now view controllers are typically
not that large in memory usage.
I mean often you hang a lot of
things off the view controller,
some of your model data and some
other data that can be large.
That we just talked about.
View controllers themselves are typically not that large.
So you typically don't want to
release your view controllers.
If for no other reason than it can be kind of tricky
to maybe reconstruct them correctly and everything.
So typically you wouldn't need to release those.
And you might have some other state in your app, where
there's a trade-off versus, that I mentioned earlier
about memory savings versus time to recreate.
And for this trade-off, for those things,
unfortunately we can't give you a 100% correct answer
of what you should do there, although we're going to have
some suggestions in just a few minutes for some technique
that might work, that might help you in a few cases.
But before we get to that, I wanted
to talk about preparing your UI.
So this is another responsibility you
have when you're entering the background.
So, so again, you're going into the background,
your UI is not going to visible anymore,
so what things do you need to do to prepare your app?
Well you might want to pause your app and even
today, you do this if you have a game especially.
It makes sense if the SMS comes
in or an incoming call you know,
it's very polite to the user, to pause your application.
And you typically do this in the applicationDidResignActive
callback and this continues in IOS 4 you still want to,
if you use alerts and action sheets in your app
and your app is and the user hits the Home button
to send your application to the background,
if one of those action sheets or alerts is up,
you need to think about whether it makes sense to
leave it up or to kind of cancel it and take it down.
So say in my journal app, I had a way for you
to delete an entry and when you said Delete,
I pop up an action sheet and you
know say, are you sure, yes, no.
Well, if the user did that and then left the app, hit the
Home button and came back a week later and the app popped up
and all he saw was this dialog which said are you sure,
yes, no and that wouldn't be the best user experience.
I mean the worse case they could actually oh, yes I'm
sure and then they delete something they don't know.
So in that case it would make sense probably for
that app to, when you're entering the background,
to just dismiss that programmatically,
as if they had hit no.
And when they come back to the app, if they
have to reselect the entry and hit Delete again,
that's a much better user experience
than just having this alert box.
So that's something to keep aware of.
And finally, the system is going to
automatically take a screenshot of your app.
When your application returns from
applicationDidEnterBackground,
the system is going to take a screenshot and it's going to
use that screenshot when it's animating back into your app.
And so if you have sensitive information on
there or some kind of animations or something,
some kind of UI that you don't want to be visible
during that animation, then this is your chance
and this is the time to update
your UI so it doesn't show that.
OK, now there's three responsibilities which I have grouped
together, which we'll go through now about networking
in Bonjour and some other system resources.
So if you're using listening sockets in your app, so you're
opening up a listening socket system, external server
or another device can connect to your application,
to get access maybe to some service you're providing,
well you have to be aware that if your application is
you know, in the suspended state in the background,
it's not going to be able to respond
to those connection attempts.
So you know, this external server or whatever
might connect, might try to communicate
with your application, well your app can't communicate.
And so that's a bad user experience.
Who knows what the server is going to do when
it gets to this situation and so it's best just
to close those listening sockets as your
application, before your application is suspended.
And if you're a fast app switching application,
again your last chance before your application is
suspended is when you're entering the background.
And of course, then if you, when the
user brings your application back
to the foreground, you can restore that listening socket.
Re-open it.
Now Bonjour, if your application is using Bonjour,
to either advertise a service or to browse
for a service, so there are two things with Bonjour.
One is the first is similar to the listening sockets.
If you're advertising a service and then your
app is suspended and someone, some you know,
someone external sees oh, this device is
advertising a service, I'm going to connect to it
and try to you know, connect to that service.
Well, they make the connection, but they're not going
to be able to communicate with your application.
And so that's a bad user experience and what's more,
especially in the case of browsing for a service,
if you leave your application browsing
for a service when it's suspended,
that's going to be using a lot of
power on the device, for no benefit.
Because since your application is
suspended, even if it discovers some service
out there, it can't take advantage of that.
It's not allowed to execute any code.
And so because of these two usability and battery
life problems with Bonjour and suspended apps,
the system can choose to cancel those Bonjour, either
your publish or your browse, while the app is suspended.
And so what does that mean for you if you're using Bonjour?
Well, when your app resumes, you need
to be prepared for errors on Bonjour,
because those operations might have been
canceled by the system while it was suspended.
And that may mean you need to restart your
Bonjour, you might need to update the UI,
if you were showing something Bonjour related in your UI,
now you might need to update that as part of your resume.
You'll see there's a reference.
There's a couple talks for networking in Bonjour, that
we have references to at the end of the presentation
that they're going to talk more about these interactions
between multitasking and networking in Bonjour.
OK, so another big one, another big thing you need to
be aware of when your application is in the background,
either background running or background
suspended is, don't use the GPU.
So it's off limits.
So for instance, if you do something like create
an EAGL context or you just issue OpenGL commands,
the system is going to be required to terminate.
Is going to terminate your application.
The GL, the GPU was reserved for the
use of the foreground application.
Again this is something we did with multitasking to ensure
that that front application remains
responsible, responsive and usable for the user.
And again, it's enforced in the background running state
and again, the natural thing, the easiest way to do this
and the way you should take care of this
is when you're entering the background,
you're going to need to stop your GPU usage.
And generally need to stop drawing
altogether, stop using OpenGL altogether.
And the last of these kind or another of these
little responsibilities is shared system data.
So this is another case where the system will unfortunately
be required to terminate your application when it's
in the background, in this case when it's in background
suspended or when it enters background suspended,
if it's holding exclusive access to some shared system data.
So what do I mean by shared?
What's shared system data?
Well we have a number of APIs that allow you to access
Calendar, Address Book, music and media libraries.
Those are all, all those APIs are basically
wrapping access to some shared system data.
You know, your address book, your contacts are
shared, any app on the system can access those.
And so the system can't allow a suspended app to hold
exclusive access to any of those or else you know,
some other apps wouldn't be able to use that resource.
And so it enforces this again, as your
application is entering the suspended state,
it enforces this by terminating your application.
And once again, our old friend,
applicationDidEnterBackground is
the place to take care of this.
OK, so now let's talk quickly about some on resume.
When your app comes back to the foreground.
Well it's kind of the converse of what we talked about.
The system is going to take care of some things.
The things that it kind of freed for you or flushed
for you, it's going to restore them for you.
The backing store, you know, it's going to
recognize that your app is coming to the front,
you're going to need to draw your UI, it's
going to restore that backing store for you.
If you're using image named, that cache is going to
repopulate as you create images, as you request images.
If you're using these other technologies, some of
these other technologies, SQLite, Core Data, NSCache,
those are restored as needed, on demand,
as necessary the information will be pulled
from your backing store into your application's memory.
Same thing if you're using a flat file, but if you're
memory mapping it again, the system as you access that file,
read and write it, it will move the, it will move the
data as necessary from the backing file into memory.
So again, those are some things we give you for free.
Some things you need to do on restore.
Unfortunately, you know, we can't give you
just oh, here's the right way to do it.
Always do x, y, z, you'll be fine restoring.
It's very dependent upon what your application
data is, what your application state looks like.
So again, it's this trade-off between the memory
size you'll save by freeing up your application state
and the time it will take when your
application resumes to restore all that.
But one quick thing we'll show you and many
of you, you know, will be familiar with this,
is to do what the system was doing
for you in some of those cases.
So basically, lazy.
It's a lazy restore of your data.
If you use a lazy kind of implementation for at least some
of your data, it might not make sense for all your data,
but for some of your data, this will allow you to
basically release objects when you go into the background
and free up that memory and then when you resume you
don't have to do anything explicit at resume time like oh,
I need to regenerate this data and that data and that data.
I hope I didn't forget anything.
But just on demand, as that data is needed,
it'll be resumed, you can restore it.
So here's a very simple example of lazy state restore.
I have my application state, I'm just, it's an array of
these my data types and when I want to access one of these,
instead of just indexing directly into the array saying
grabbing it, I use this simple accessor function which,
first check to see whether it's been initialized,
if it hasn't it goes out to my backing store,
which I have wrapped with that data
controller here and just initializes my
in memory representation of that object and returns that.
So that's done, so now when I want to access
some data, I don't' need to, I just access it.
The first time I access it, it'll get restored.
For instance, it's not there and so when I
go into the background, I just, I can release
and free them all up and free up all that memory.
And so again, for some of your applications state, this
will make sense and for some it won't and just on a case
by case basis, it's just another
tool that you can potentially use.
So system changes.
So, so when your application is suspended
you know, the whole world doesn't stop.
Things are going on all around your device.
The networking is changing you
know, your locale might change,
other changes might happen, the user might change settings.
And so when your app, what the system does for you,
while your app is suspended, it's going to collect these,
it's not going to throw them away so that you're like
unaware, but it's going to collect them and coalesce them.
Your application is completely suspended so it can't, it
doesn't receive those notifications while it's suspended,
but when your application resumes all those notifications,
those system change notifications,
will be delivered to the application.
And so your application must be prepared to
handle this burst of notifications coming in.
And so you want to make sure that whatever code
you have that deals with these notifications,
that it's not going to take too long to execute,
because that could delay the resuming of your app.
It could make the app seem sluggish when it resumes.
It can make your UI flash and rapidly update as
it responds to all these notification changes.
And a great technology, I'm not sure if the talk has already
happened, if it has you can see it on video or check your,
the schedule, is the Grand Central Dispatch and Blocks Talk.
That's a great way to move work off the main thread
and it might help you in, to handle this situation.
And so, this is a little bit of an eye
chart, but these are basically all,
you can look in the documentation and see all these.
These are all documents.
These are basically all the types of
changes that can concur while your system,
while your app is suspended and
that you'll need to deal with.
So last I want to talk about, very
quickly, is network connections.
Network connections while your app is suspended,
this is kind of like the system change notifications,
you can lose your network connections for a lot of reasons.
You know, the network conditions can change, your
location can change, all sorts of things can happen.
So this could even happen today of course, with your app
when the say the device is locked and sleeping, when you're,
but it's much more likely to happen
when your app is suspended.
So when your app is resumed, you need to be ready, on all
your network connections, you need to be ready for errors.
You know, because those connections could be lost
and you need to handle those errors correctly.
Don't ignore the errors.
And you know, you have to take the right action.
Often it will just mean oh, you know, I lost my
connection to the server so I just need to you know,
close that one down and just reestablish connection.
It's often that easy.
But it's definitely something you need to test for
and be aware of in this multitasking environment.
Now here's a quick code example.
This is not meant to be like a template which
for every application you would put in there
and it would be the exact way that you would
want to do your applicationDidEnterBackground,
where a lot of these responsibilities are implemented.
It's just kind of give you the idea that you know,
you're going to have a lot of things that you need to do
or several things that we talk about
that you need to do here, save state,
reduce your memory usage, prepare your UI if appropriate.
Maybe if you're using some listening sockets
or what not, you might want to close them down.
And on the resume side there's
a shorter list because let's say
for example we're using this lazy state restore technique
and so actually you don't need to do anything for state.
Again that's not going to necessarily solve
everyone's problem but it's something to keep in mind.
And again, in the earlier example, I closed
the listening socket when I was going
to background, so I want to open it back up again.
And so now that's kind of, that was the responsibilities and
best practices and now I'm going to turn it back to Dave,
who's going to talk a little bit about the
multitasking and development tools that you can use
to help with your multitasking development.
>> David Myszewski: Thanks
[ applause ]
So as part of multitasking, we've enhanced some of
our development tools that will help you introspect
to the feature, the states of your application and
figure out what's going on at any given point in time.
One key tool that we provide is Instruments and Instruments
provides this nice timeline view, things like memory usage
and CPU usage over time and one of the
great new features of Instruments is
that your application lifecycle events are flagged.
So if I am sitting here running stocks and I hit
the Home button, then Instruments will flag the fact
that the application for a short period of time went
to the background running state and then it cleaned up,
it saved state, paused UI, things like that.
And then the application was suspended.
Then maybe later on the user might hit your application icon
and then Instruments will show that
your application is running again.
The two states that are going to background
running and to background suspended,
you may want to watch your memory
usage between those two states.
Because that's where you'd be freeing up all your memory
and so you can use something like the object outlook tool
to see just how much memory you
freed during that time period.
So Instruments provides a nice want to integrate with your
apps so that you can see what it's doing in these states.
You know, maybe you have a function call that
was too expensive or maybe you have some memory
that you think we should really release, then
Instruments will allow you to see exactly what's going
on in your application, as the user
transitions between states in your app.
A few notes about the simulator.
Much like we say in other talks, the simulator
is not a complete replacement for the device.
It's always important when you write your applications,
to test them fully on the device because that's
where everything will be exactly how the customer sees it.
We integrate most of our multitasking, most of the
multitasking features that you as developers will need
into the simulator, so fast app switching is fully
supported, task completion, local modifications
and if you want to test any sort of integration with your
multitasking UI, you can all do that in the simulator.
But there are a few things that we don't provide
for multitasking, in particular background audio,
location and VoIP services and the significant
location changes, aren't provided in the simulator.
Your Mac doesn't have a GPS chip, so can't
provide that and of course, push notifications,
much like in iPhone OS 3, still
aren't supported in the simulator.
But for most of the work that most of you will be
doing, the simulator is a great environment for testing
out multitasking, just make sure
that you try it on the device.
Then the debugger changes just a couple of
things about how your application behaves,
so that you as developers, can
better debug your applications.
So, it is important to test your app outside
of the debugger, not just in the debugger.
So what are the changes?
Well those new applicationDelegate callbacks, we only
have a few seconds to get through those callbacks
and let's say you have a problem in one of those
callbacks, it may be a bug or maybe you want
to see well why am I not freeing up memory.
Well it would be really unfortunate if we
only gave you six seconds to debug your app.
That's you know, I'm sure you're a fantastic
developer, so are we, but six seconds isn't long enough.
So it's probably not long enough for anybody.
So we don't enforce the time limits there and
in the test completion expiration handler,
which you'll hear more about in the second
talk, we also don't have any sort of time limit.
So the debugger resumes or allows you to
debug your apps a lot more effectively,
but that means you need to test
things on the device as well.
So to conclude, we went over a bunch of the best, the
behaviors that you want to implement for fast app switching,
the API that you need to adopt and these are
APIs that every application should be adopting.
You'll want to do it regardless of whether or not you're
the type of application that doesn't need to execute code
in the background and just needs to be there
so that the user can quickly resume to it
or if you're an application that runs in the background.
You still want to do all of these things that we
mentioned in the talk, like reduce memory usage.
All applications on the store can benefit from fast
app switching because you can resume really quickly,
we can preserve your state and we have you know,
great integration with the multitasking UI.
But we have those other services that allow you
to execute code in the background and do things
that you couldn't have done before
and for that we have the second talk
which will describe those services,
in a lot of detail, this afternoon.
So that's in the Mission at 3:15.
We also have a few other different
talks that might be interesting.
Various tools, learning how to, what some
of the new features and instruments are
so that you can intersect your app even more.
Blocks and Grand Central Dispatch, which
David mentioned, to free up your UI.
Simplifying networking and another networking
talk that will tell you a little bit more detail
about how to handle various network conditions.
So thanks for coming.