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.
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.
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.