[ Silence ]
I'm Steve and I'm going to talk today about what's new in Foundation Networking.
So, Foundation Networking gives you new API this year: NSURLSession.
You might have heard this talked about yesterday during the multitasking APIs talk.
NSURLSession is a replacement for NSURLConnection.
The big benefit it's going to give you right off the bat is out-of-process background transfers.
It's a way of providing your applications with the ability to get work done when you're not running.
It's available on iOS 7 but also in OS X Mavericks.
I'm mostly going to talk about some enhancements to the Foundation frameworks around some specific technologies, NSNetServices, single sign-on an iCloud credential syncing.
So off the bat we have, you know, sort of a generic chart diagram of where your application sits.
Your app sits on top of maybe WebKit, MapKit, UIKit on iOS.
This also sits on top of the Foundation Framework which contains the Cocoa container classes.
There are classes for scheduling, for file transfer and networking.
Foundation sits on top of CoreFoundation and CFNetwork.
Now, the reason there is a separation there is because a long time ago, we have the support in API called Carbon.
Nowadays, almost all the work you guys do is going to be based on the Foundation layer.
But the CoreFoundation/CFNetwork layer is still there.
Lastly, networking on our platform is built on top of BSD sockets with enhancements in the kernel for our specific mobile needs.
In these different frameworks at these different layers, there are different APIs you can use.
BSD Networking uses BSD Sockets and this is obviously well known.
But on top of BSD Sockets, the CoreFoundation and CFNetwork layer gives you access to a stream API in CFStream which allows you to access files streams or sockets streams.
CFNetServices which allows you to publish and subscribe to or browse for Bonjour services.
And CFHTTPReadStream which gives you a way of issuing an HTTP request and receiving the body of the response as the stream data.
Foundation though gives you some nice Cocoa APIs on top of this.
NSStream is a direct replacement for CFStream.
There's no need to use CFStream if you're using NSStream.
NSNetServices just wraps CFNetServices but it does so in a delegate-based Objective-C ARC compatible way.
But NSURLConnection is more than just a single class.
NSURLConnection is a suite of classes, a bunch of classes, it's also the name of a class which is a little confusing, but it's true.
Now, today we're going to talk about we're going to talk about NSNetServices a little later, but mostly I'm going to talk about NSURLSession and then NSURLConnection, how they relate, why you're going to use one over the other, and why you're not going to use one.
So going back in time for NSURLConnection it describes both a technology that is the suite of classes that are necessary for doing HTTP loading, and it's a specific class in that there is an instance of a class called NSURLConnection.
These classes were originally written for Safari back at the dawn of the millennium.
And they were first made available in 2003 which I think the same year we introduced the Power Mac G5 back when the bits all went the right way.
[ laughter, applause ]
It provides URL resolution thank you.
It provides URL resolution and loading.
What that means is when you have an arbitrary URL like a file URL, NSURLConnection is going to be used to load data out of a file URL or out of a data URL, or you can connect to an FTP site, but mostly HTTP and HTTPS is what people end up using it for.
If you had your own protocol that you wanted to register, you could register that in your process using the NSURLProtocol class.
So NSURLConnection as an API encompasses all the loading machinery for the Foundation layer.
Configuration of an NSURLConnection occurs by tweaking the NSURLRequest object.
There are a couple of properties you can set on an NSURLRequest, some headers maybe you can set, and some policy decisions you can set.
But by and large, NSURLConnection works by looking at the global state of your process and global configuration options.
NSURLConnection also gives you access to proxies automatically, and it challenges you for credentials when an HTTP request is challenged by a server.
So what this looks like is you create an NSURLRequest object, you create it with the URL.
You configure it how you want and then you create an NSURLConnection object.
This object represents the sort of the transient of state of the request as it's being made.
You create the connection with a delegate which receives information about the load as it's occurring.
NSURLConnection then looks in the global state.
It captures the cookie store, cache, credentials and any protocols that are loaded in your process.
And it produces an NSURLResponse Meta-Data object, and zero or more NSData objects which represent the payload of what you're getting.
So in your process, you have some networking needs, right?
And you're just going to keep doing this over and over.
You're going to create a request, you create a connection, bind it to your delegate, and the framework is going to bind to the global storage over and over and over to produce these response objects.
So a problem is if another framework in your application also needs to use this global state, it ends up using and overriding the same global state.
You can't both have your own protocol handler as you can't both have your own global cache objects.
So the first thing NSURLSession does is it continues the process of having confusion over whether it's the name of a class or a technology.
[laughter] I know that's important.
So it replaces NSURLConnection as a technology, but it preserves almost all of it.
So NSURLConnection as a class goes away and to be replaced by an NSURLSession class, and NSURLSession has some additional classes associated with it.
NSURLSession is the configurable container for putting network requests in to.
It gives you better HTTP options based on feedback we've gotten over the year.
So I want to be able to this.
Well, you couldn't before, now you can.
It gives you access to the storage objects on a per session basis.
So you can have private storage objects.
It improves authentication handling by having an explicit authentication challenge mechanism for connection-based requests.
In NSURLConnection, when a request was challenged by a server to authenticate against a pipe, for instance an NTLM server, the challenge would come back for an arbitrary request.
You wouldn't know necessarily which request would get that challenge.
Now, challenges for connection-based of are sent directly to the session delegate.
And I have this rich delegate model which is kind of weird way of saying this, but NSURLConnection had some asynchronous convenience routines, but the problem with that is that they wouldn't use any delegates.
So either the asynchronous routine would work or it would fail, now you can have a hybrid approach where there is an asynchronous convenience routine, but it can also use your delegate to do auth.
Session gives you uploads and downloads to the filesystem, that's sort of the preferred way to do uploads and downloads.
There's sort of a policy shift in Session in that the configuration goes in via Session instead of NSURLRequest and we try and separate the body of a request, that is if you're doing a post of an image, from the request envelope itself, it's sort of like you don't want to have a post star, you want to have an envelope.
We've always had the separation of that response meta data from the actual payload itself.
So just trying to make this API consistent between request, response, payload, payload.
And NSURLSession gives you access to out-of-process uploads and downloads.
The nice thing about that is it's just a configuration option.
When you create a session, you specify, "Well, I want request that go into the session, could be done on a background."
What it allows us to do though is when your process is no longer running, it's been suspended, we can continue your download in the background taking advantage of everything we've learned about the user's network use and their battery life.
Using UIKit on iOS 7, we key in, we take advantage of the new multitasking APIs so that your application can have updated its interface and provide a better experience for the user.
You're going to download your content and have it available in the UI.
So this looks like, well, it's a big object, a big square object called NSURLSession.
And you create a session with a configuration object.
This is where you're going to specify any HTTP options and the various storage objects.
And you create a session with a delegate.
Delegate gets called on a sort of per request basis.
When you throw a request into a session, you get a response out and you keep using the same session over and over.
So as Session is an API, there are a bunch of additional classes you need to know about, not nearly a bunch but some more.
OK, so the first one is the configuration object.
This is basically a properties dictionary of how you want the session to behave, the task object which really is the replacement for connection.
So you can think about Session is this larger ball, and Connection goes away and these taske objects get created on a per request basis.
There is a delegate protocol, the delegate object, that you're going to create to bind your session, and then the session object itself which is a factory for creating tasks.
You always create one task per request.
So this is a classic NSURLConnection example.
You create a delegate object and a URL.
I keep using setAllowsCellularAccess during this talk as an example of a property that you might tweak on a request.
So in this case, you create an NSURLRequest and then you modify the request to say, "I don't want this request to go over cellular."
You create an NSURLConnection object using the class method connectionWithRequest, you bind it to your delegate.
Your delegate then gets called with didReceiveResponse, didReceiveData, didFinishLoading referencing this connection object.
Now in NSURLSession, it's pretty much the same, but there is more configuration upfront but less work later on.
You create a delegate conforming to the session delegate protocol.
You create a configuration object.
There is a bunch of class methods for creating configuration objects based on what you're going to try and do with them.
In this case the defaultSessionConfiguration object actually gives you the same sort of configuration options that NSURLConnection would see.
So if you had created this task with an NSURLConnection instead, you would have sort of the same behaviors.
But instead of modifying the request to say AllowCellular, all the requests that go into this session that I create are going to not use cellular.
So you create a session, you bind it through a delegate and you give it a queue where the messages for your delegate are going to be received.
You don't want to block in your queue.
All the callouts to you are sort of asynchronous or they're intended to be asynchronous or either informational or they'll be a completion handler.
If you use the session once you get all set up, you create a URL, and then you can use a dataTaskWithHTTPGetRequest which returns to you an NSURLSession data task object.
Actually, I want to talk about one more thing here.
The data task object I've mentioned NSURLSession task, NSURLSessionDataTask is a subclass of NSURLSession task.
And I'm going to talk about that a little bit more, sorry.
Right, so NSURLSessionConfiguration.
NSURLRequest did not have a lot of configuration options.
So now we're adding support to subclass and set your own private cache both using credential storage.
We maintain the ability to set the cell usage flag and network service type from NSURLRequest.
We give users the ability to tweak the maximum number of connections through a host.
In NSURLConnection, behind the scenes there is this global pool of sockets that have been opened and we come up with some number of connections based on internet standard usage for how many connections we want to open to a host.
But what we've heard is that people want to tweak that.
They say "I really only want one connection to a host ever.
I'd like all request to go up in this one connection."
So now you can do that.
We have the resource and network timeouts.
This is nice because while NSURLRequest has an implicit timeout when you create one, or you can set an explicit one.
That timeout is for network transfers.
If you're getting a long-lived request and maybe you want to get a request, you want to get the bytes out of request, but only one byte is coming in at a time, if you don't get any bytes for that network timeout, then the request times out.
So you can imagine doing a get where it might take a week to come in and never timing out.
So there's a new timeout, the resource time out.
If I can't get this entire request within this timeout, then I want it to cancel.
This is particularly important if you create a background transfer.
I want this file, but if I can't get it in three days, forget about it.
I'd rather hear that it failed.
You can now set the minimum and maximum TLS levels to, you know, ratchet down security or open it up for your particular server.
You have access to the HTTP proxy dictionary directly on a per session basis.
This is the same dictionary you would get from systemconfig, but now you can modify it if you had special proxy needs within your application and we're going to use that proxy dictionary for all requests that travel through the session.
We have some of the same options on request as far as cookie handling is concerned, whether you want to apply cookies as they go out, but you can also specify the cookie acceptance policy.
HTTP pipelining is something you can turn on and off at this on a per session level.
And you can set additional headers that will be applied to any request.
If a header is already present, we don't override it.
But if you wanted to set the user agent for any outgoing request, you could do that here.
Lastly, protocol handlers are kept on a per session basis.
There is still the global protocol list.
But if you have your own protocol, it would be better to bind it to a particular session and use that session and expect to get that protocol.
So there are some factory constructors for creating sessions.
The default configuration sort of captures the global state that NSURLConnection sees.
There is a factory to create an ephemeral session configuration.
This is basically the same as a default configuration except that it initializes the storage objects to be in-memory only.
This is how you would implement private browsing for instance.
And there's the background session configuration which creates a configuration object that references an identifier.
That identifier is what you use to reconnect this session to the background work.
Configuration objects are always mutable and they're copied whenever they get used.
So when you create a session with one, it'll create a copy of that.
And while you can get to the configuration inside of a session, you can't modify it.
So the task object, this is the thing that actually replaces NSURLConnection in the class.
And it represents, you know, the state of a loading resource.
When you look at it in the header, the immediate thing that comes out is that it has a lot of properties.
The properties that previously had been reported via delegates are also available through the task object itself.
So you can look at a task object and find out how many bytes have been transferred, how many bytes are expected to be transferred.
It offers the same cancel, suspend and resume that NSURLConnection does.
There are two subclasses for data task and upload task.
This is really done just as sort of syntactic sugar so that we understand that there are different types of work that's going on.
And in particular, you can't schedule background data task.
You can schedule background upload or download tasks.
Download tasks don't really offer anything over the base class task except for this cancelByProducingResumeData.
If somebody hits pause in the UI, you want to stop the background transfer or foreground transfer for that matter.
You're given this resume data blob.
Later on, your app can go ahead and create a download and bind to this resume data and we'll continue where we left off.
The delegate that you create the session with has messages keyed to the specific task type.
So all tasks can finish loading, but only data tasks receive incremental data, and only download tasks receive that final URL where the file is.
So the class hierarchy, you know, looks like this.
You've got a session task with these methods on it.
I think there's a status method, but there are also properties in there that you can look at.
DataTask is a subclass of SessionTask and UploadTask is a subclass of DataTask.
Any task can have an upload payload, including a download task which is weird when you think about it but it's true.
You can do a GET for a resource and have it have body data.
It's not my protocol.
[ laughter ]
So the DownloadTask subclass also has this extra method cancelByProducingResumeData.
The delegate objects that you create your session with, you create a single delegate object, right?
So each session has one pointer to your delegate object.
There are different task types are broken out into different protocols, but you can just implement them all within one class.
The delegate itself is strongly referenced by the session.
And in order to break that cycle, you have to invalidate a session.
When you invalidate a session, all the work inside the session gets canceled or finished, and then the session did finish or sorry the session did invalidate, delegate method gets called.
At that point we release your delegate.
Now a Delegate message may block loading.
Some of them are informational like didReceiveData, gives you a data blob and then goes back to work.
Some of them, like didReceiveResponse, require you to return something.
In NSURLConnection, you had to return something immediately, but in the SessionDelegate model, you're given a completion handler.
Then you invoke that completion handler to continue the load.
So it's OK to schedule a session on say the main queue as long as you know that the work you need to do needs to be done via this completion handler.
SessionDelegate then is sort of the overarching a session should implement this.
I mentioned way earlier that there's an authentication challenge specific to connection types as opposed to request.
Those come in through the URL session didReceiveAuthentication Challenge:completionHandler delegate method.
This is going to be for connection-based auth like in NTLM also for SSL auth like here's the server certificate, or if the server requires a certificate from you.
We implicitly handle Kerberos on both iOS 7 and with OS X Mavericks.
So you should be aware that it's happening that you might have a Kerberos authenticated connection, but you actually won't hear about it through this delegate.
The other delegate method that we care about is didBecomeInvalidWithError and this is where when you've invalidated the session, this is the method that gets called before your delegate is released.
So data delegates are interesting because this is for doing incremental loading of data.
These are basically some of these are optional, right?
So if you don't care about redirections, you don't have to implement willPerformHTTPRedirection.
If you care whether you want to do something different for redirection, then you implement this and it gives you the new request.
This is where you're going to go to and call the completion handler with either that new request, the request where you'd rather it go to or nil.
If you pass nil, then we treat the request sorry, we treat the response that specifies the redirection as the data you're getting.
Sometimes you want to do an HTTP Get request, you get a redirection response, but you'd rather have the body of the response rather than the new location, so that's how you would implement that.
When you have a request based authentication challenge, they come in through the didReceiveAuthentication Challenge, the task didReceiveAuthentication Challenge.
This is where you create a credential for basic digest auth or any sort of proxy auth on a per request basis.
As the request is uploading data through a server via POST, we periodically call this didSendBodyData delegate method if you implement it.
This data is the parameters here are actually mirrored in the task object itself.
So if you look at the task object, you'll see these things being modified, and you don't necessarily need to implement this.
needsNewBodyStream needs some explanation.
This was added to NSURLConnection because when it is a carryover from NSURLConnection delegate, because when we're doing an HTTP post, sometimes the server is going to come back with a challenge or some sort of server error that we can recover from.
We could resend this request.
But because that because streams are not rewindable, we want it to have the data to send them again.
So we will call your needsNewBodyStream and your needsNewBodyStream delegate to ask for a new stream so we could resend the request.
If you didn't implement this, then the request would fail and you'd have a confused user.
The problem is, you know, when you're doing your testing in-house, this never gets called because everything is working correctly.
But out in the field, you know, there's one in a million chance this is going to happen, but one in a million chances happen 9 times out of 10, and so your users will be confused.
[ laughter ]
needsNewBodyStream must be implemented if the upload you're doing is from a stream.
Sessions lets you create and upload from a file though.
So if you are implementing uploads via the filesystem, you don't need to implement needsNewBodyStream.
If you're doing an upload via a stream, we require that you implement it.
Lastly, all tasks finish with error.
NSURLConnection had didFinishLoading and didFailWithError.
NSURLSession just has didCompleteWithError, error will be nil if there was no error.
Note that the error that you're sent here is a transmission error, not a server error.
If the server responded with 404, as far as we're concerned we did our job, we sent you request and got a response.
The only errors you're going to get here are errors that are specific to, "We couldn't find the host," or "the connection was lost," or some horrible thing happened.
Data tasks have a couple of specific data-related delegate messages.
First one is didReceiveResponse.
Now, this is interesting because when the server gives you a header back and it starts sending body data, you might decide that the response you got doesn't need to go to memory, you just want it to go to disk.
You can use didReceiveResponse now to specify that this data task that I'm about to get data for, I'd rather have the data go directly to disk.
So you call the completion handler with a disposition saying "become download.
" And the next delegate message gets called to say, "Your data task is now dead.
Here's a download task instead.
" And all the flow goes through that download task.
As your resource is being loaded from the network, if you kept it as a data task, you'll receive zero and more didReceiveData messages.
The NSData objects that you get behind the scenes may be stitched together from many NSData objects.
So in the past, you would just have gone [NSData bytes] or bytePointer or whatever.
We would encourage you to instead use the enumerateByteRangesUsingBlock API because we could give you now a 4 Meg buffer.
We just downloaded your 4 Meg.
Internally, maybe that's cut up into 50 different segments and if you just ask for the byte pointer, then we have to flatten all that, and that's not good for anyone.
Lastly, data task caching - only task can be cached.
If you don't implement willCacheResponse then we go ahead and cache for you all things being considered, whether caching is enabled in your session and whether the resource is cacheable and whether the server said to cache.
Note that this won't necessarily get called because there could be something maybe the resource is too big to fit in the cache or maybe the server didn't want it to be cached.
So we won't always call your willCacheResponse.
So really, the only reason to implement it is to say, "No, I don't want to cache this particular response type," or if you want to modify the user info dictionary associated with the cache response.
Download tasks always download to a file.
We create the file for you.
We put the bytes into it and then once the download is complete, we call didFinishDownloadingToURL.
We give you a reference to a file URL which you then need to copy or move because we're going to delete that file shortly thereafter.
As that file is being downloaded, we give you access to the number of bytes that have been transferred for your progress use.
And if you created your download task using the resume API, then we're going to call didResumeAtOffset.
One thing to note is that the offset you're given here is the real offset at which we began resuming the download.
We may previously have said, "We've downloaded 4K," but when you get to Resume, we've decided "We're can only trust 2K of that.
" So that number may go backwards from what you were previously told.
So the session object itself.
There's a default session object that you can use and this shares the same world as NSURLConnection.
As a matter of fact, the configuration object inside of a shared session, if you look at its Cookie storage, it's the same as the NSURLConnection Shared Cookie storage.
But you're going to create your own private sessions with private either private configurations or using the default configuration.
But you're going to create your own session usually.
When you're done with your session, you have to invalidate it, and then that delegate message didBecomeInvalidWithError is called and then your delegate will be released.
Session is the object that creates data upload and download tasks, but it also provides these asynchronous convenience APIs with a various type of task.
And the nice thing about those is that they give you access to your delegates authentication method.
It also lets you cancel them.
So NSURLConnection send asynchronous request as an existing API.
Once you fire that, you have no control over it.
It's going to finish or it's going to fail.
But with Session, you're given a task object back.
You can monitor that task object and you can cancel it whenever you want.
So to create a session with a custom configuration, in this case, I'm going to implement private browsing.
So we create a new configuration object using the ephemeral configuration delegate or class method.
We create a session with that configuration object.
Whatever the URL is, we throw it into the session with data task, with an HTTP get request, in this case I'm using the asynchronous convenience API which will invoke my block with the data once the data is resolved.
If I wanted to further customize this, I would have added whatever configuration I wanted on top of the configuration object that I created initially.
So to create a DataTask, it's sort of just like NSURLConnection, you throw an NSURLRequest, they are convenience APIs for throwing just for all URLs into it as well.
The convenience API version of this takes an additional completion handler and we are just going to invoke the completion handler.
We invoke it on the same queue as your delegate if you had created the session with the delegate.
Upload tasks can be explicitly created from a file or they can be explicitly created from a data object or they can be implicitly created with a stream.
When you do uploadTaskWithStreamedRequest, we take your NSURLRequest and even though NSURLRequest has an existing API for setting a body, if you throw it in to a session through uploadTaskWithStreamedRequest, we ignore the body.
We will always call your needsNewBodyStream method to get a stream when we need to trasnfer that request.
There is no convenience routine for that model of upload task, but there are convenience routines for upload from file or upload from data.
Download tasks are similar, you create them with an NSURLRequest which identifies, you know, whatever resource you want to get off the network.
Or you create it with the resume data that you previously had captured by cancelling with resume data.
There is a convenience routine for both of those as well.
It calls this block with the location of the file that we downloaded.
Again, you have to copy or move this file because we're going to delete it.
If there was a connection error during a transfer and we're going to be able to resume that, so let's say your user walked out of Wi-Fi range and we lost the connection, we might return to you a connection error.
In the user info of that error, there is this key NSURLSessionDownloadTask resume data where we will have squirreled away resume data so that you can restart that transfer later.
So background transfers, this is where we're going to talk about the ability to do work while you're not running.
You have to use the delegate model for background transfers and we only support HTTP and HTTPS, obviously it doesn't make any sense to do a background transfer from a file URL.
You use exactly the same delegates as you do for upload and download tasks.
We have to make some assumptions though while you're running.
So we don't bother calling you back to take a redirection.
We're going to assume that any redirection should always be taken.
And there's one property I want to call out on the configuration object which is this discretionary property.
What this tells us is that when we're doing a background transfer for a session that's configured using this discretionary property being true, is that we can take advantage of the state of the machine to prioritize this download to only do it when things are really good.
Typically, that's going to mean I'm on Wi-Fi and I'm plugged in.
If you're in the foreground and you don't specify this property, your download actually has a high priority, you know, your user is sitting there, you've created a download task and you're going to watch this thing make progress.
So we want the user experience there to be that the work is being done right now.
If you started your download task when you were in the background though, we assume that discretionary is true, we're going to prioritize it as if, you know, this session were created with the discretionary flag being set to true.
So if you're a foreground app and you don't care how long it's going to take for this resource to come in.
I don't want to say, you don't care, I mean you care, but you don't care that much.
You set discretionary to be true and we're going to do our best to prioritize it given the constraints of the network and the power is the current state of power.
So what this looks like then is that it creates session with an identifier, a background session configuration with an identifier.
This causes a daemon to come into existence.
You create your download object, your download task and that starts the work happening in the background daemon.
While your app is running, it receives progress updates, I downloaded this many bytes.
But if your app stops running, the work continues off in the daemon.
And when the daemon is done downloading your file for you UIKit application, we're going to re-launch you, you re-create your session which reconnects to the daemon and then the daemon can tell you, "Hey, you're completed and here is the file.
" So, while your app is running, you create a background pass, you're going to receive these update messages.
If you're a UIKit app on iOS 7, when you're not running, we're going to have to launch you if we need credentials or if all the requests that you have enqueued are complete and we're going to call the application handle events for background URL session completion handler delegate application delegate.
What you do then is reconnect the session to the background daemon.
You're going to receive all the delegate messages for the outstanding tasks and then when you're done, you call that completion handler to update your snapshot.
When you do reconnect, you can probe, you can ask the session for any outstanding tasks.
So you create a background session configuration, you create a session then you call getTasksWithCompletionHandler which goes off to the daemon, gathers up all the task objects and sends them back so you can interrogate them.
But you will receive delegate messages for a task.
You don't have to call the taskWithCompletionHandler.
All right, so Dan is going to come up and do a demo of this.
Thank you, Steve.
All right, good morning everyone.
So today, I'm going to do a demo of an iOS app that uses the NSURLSession API to do a background transfer.
So this app does two very simple things.
It downloads an image in the background and it can de-reference an old pointer.
So you should only be doing one of those things in your apps.
So, I'm going to hit this Start button and now you can see that our download is making progress.
So now, as it gets us [inaudible] progress, I'm going to suspend the app so now the app is no longer running but our background daemon is actually doing the download.
So if we look on this app switcher then when the download finishes, we'll re-launch the app and an image will appear.
[ Applause ]
So, now just to show you again, we can start a download and this time, instead of suspending the app after it goes for a little while, I'm actually going to hit this Crash button and now that they referenced an old pointer and it crashed.
But even though the app crashed and there's no it's no longer even a process, we're still downloading that file in the background.
So then the next time we go back to our app, the file is there.
[ Applause ]
So, now I'm going to walk you through the code and show you how I wrote this app.
So, first of all, this is here is where we create our NSURLSession and the magic here is where we created the background session configuration and pass in an identifier and again, this identifier is so that when you create this session on subsequent launches, you'll be reconnected to the session that already exist in the daemons.
So, I do this inside of a dispatch once here to emphasize the fact that you should only be creating a session with a given identifier once.
And if you want to create multiple sessions that have that do background work, that's perfectly fine, but they each need their own identifiers.
So now that we have our session, we can create downloads.
So here's how you would create a download task with that session and this is exactly like how you would create a download task with an in-process session as well.
So you create an NSURL request with the URL that you want to download and this is should also be familiar from using NSURLConnection.
And then we use the downloadTaskWithRequest method to create a download task in that session.
This is a progress callback for the download task, it tells it can and it can give you information about how many bytes have been written to disks so far.
And in our Apple, we use this to update a progress view by diving total bytes written by total bytes expected to write and that gives us our download progress.
So the fraction, we use that to update that progress wheel.
This is the didFinishDownloadingToURL delegate message and this happens when we finish writing all the bytes of the download to disk.
And as we mentioned before, you need to link or copy this file into a more permanent location because as after these returns, we're going to unlink the temporary file that we downloaded.
And we all and since this was an image, it made sense to display it so we created an image and displayed it an image view.
And finally, this is task didCompleteWithError and this is the last callback you will get pertaining to a particular task and as Steve mentioned before, if the connections exceeded and the downloads exceeded, this error will be nil and if there was a transmission error, the error will be non-nil.
And we also here call this call completion handler a finished method and I'll get back what that to what that method does a little bit.
So this leads us though to our to one more additional difference between in-process sessions and background sessions which is that in a background session, we have support in UIKit to launch you in the background when download when all the downloads in the session finished or when a particular task needs authentication.
So and this is why the application handle events for background URL session completion handler method.
So, when this is called, you'll want to reconnect to the session with a given identifier.
So in the case of this app, we actually created our session when our view controller was initialized and which that happened when application did finish launching with options was called.
So at this point, we'll already actually be connected to our session.
And then we have this completion handler and we want to what this completion handler does is it allows us to take a snapshot of your UI and display it in the app switcher and it also tells us that we can suspend your app.
So it's very important to call this when you're done handling all the events pertaining to the session.
So we only want to call this when we're done handling the events.
So for right now, we're going to save it in a property on the app delegate and we'll invoke it later.
And it's important to note that this has to be a copy property since there's a block and you have to blocks have to be copied when saved.
So let's go back to our download view controller and I mentioned this call completion handler if finished method before.
So let's see what that does.
We called it when the task finished and now what we want to do is we want to check if it's time to call our completion handler.
And we only want to that once we know we're done handling all the events for all the task that finish when your app is in the background.
So, in this case, we only did one download, but this is what you would do if you if your app did multiple tasks in the background which is perfectly reasonable.
We used the sessions get task with completion handler method and this will give us back a raise of all our data, the upload and download tasks and it won't give you back any tasks that have been completed.
So if all these arrays are empty, that means you know you're done handling all the events and we can call our completion handler.
So here we get our app delegate.
We see if we have a completion handler and if we do, we invoke it.
And it's that's how you use background uploads and downloads.
Back to you Steve.
[ Applause ]
OK, so why do we want to use NSURLSession versus NSURLConnection?
NSURLSession again provides you with access to connection based auth which is something NSURLConnection did but only by targeting specific requests.
Session gives you better HTTP configuration options that people had been asking for, for years.
These are available through the NSURL configuration object that you create your session with.
The ability to create private subclassable storage objects is something you couldn't do before.
You couldn't create a cookie storage subclass and have that available to the system views.
You could create an NSURL cache subclass but then you would set it to be the default for the system and all other processes would end up using it as well sorry, all other frameworks within your process.
These are always per process properties.
Very importantly, Session is how you get to add a process background transfers both for uploads and for downloads.
It's also going to be the baseline that we're going to build any future APIs on top of.
Session gives us a context that we didn't have before, before the context was your process.
Now within your process, there's a lot of different things going on, Session is how we're able to compartmentalize that within your application.
So we spend a lot of time talking about session.
There are some other enhancements that I want to mention that are new in iOS 7 and Mavericks.
NSNetServices is an existing API that allows you to browse or discover and connect to Bonjour Publish Services.
It also allows you to publish Bonjour Services.
You do this by creating an NSNetServices describing the type of service you want to connect to and you call this get input output stream message method.
The streams you get back, you open them and at that point, the resolution occurs, once the stream is successfully open, that means you have a raw socket that you can do your own protocol framing on top of.
There's a new property in iOS 7 includesPeerToPeer.
When you specify this property in your NSNetServices when you perform a browse, it will also browse on peer to peer Wi-Fi and Bluetooth networks automatically.
The peer to peer Wi-Fi is new support in iOS 7.
There's also a new option for publishing a service which automatically creates a listening socket for you.
So when you create your NSNetService to publish it, you need to specify this new option NSNetService ListenForConnections.
We'll listen on IPv4 and IPv6 for incoming connections and when a remote connects to that socket, we will call this new delegate method, netServiceDidAcceptConnection with input stream output stream.
You open your streams and now you have a raw protocol stream to frame your own messages onto the remote site.
Authentication in iOS 7 gets single sign-on.
Kerberos Authentication is automatically handled by device managers that have installed a profile on your device.
You can specify which connect type what type of connection should be authenticated based on the URL or by application.
And we handle this implicitly for outgoing connections.
You need to know that it's happening for your connections in your app, but you won't necessarily need to have to do anything special about it.
There is an a session, I think it was yesterday "Extending your Apps for Enterprising and Education Use" which you should check into to find that more about how to configure a system and how to respond well, you don't have to respond, how to deal with Kerberos authenticated connections.
The final API enhancement in Foundation Networking is iCloud Credential Syncing.
When you create an NSURL credential which represents the username and password or client certificate, you're presenting to the remote site.
You specify a persistence type for it so that we can keep track of it in the NSURLCredentialStorage.
There's a new persistence type called synchronisable.
When you create a credential with this persistence type, it automatically could sync through iCloud to all devices registered for that iCloud account.
In order for this to work, we have to have a new API to actually remove the credential as well.
So there's this new remove credential for protection space API on NSURLCredentialStorage.
You invoke this using a dictionary of properties and the key you want to look for is the NSURLCredentialStorage RemoveSynchronizableCredentials.
So, [inaudible], most of what we talked about is NSURLSession.
We do think this is going to be a good way for you guys to build your networking applications in iOS 7 and OS X Mavericks going forward.
It replaces NSURLConnection, but I want to point out that NSURLConnection doesn't go away.
It's still there and you can use your existing code, doesn't break but NSURLSession is sort of the preferred way to do these types of request later on.
It gives you a lot more customization over NSURLConnection.
And it very importantly allows you to get work done when you're not running.
NSNetServices adds peer to peer support both browsing and publishing and it has a new listening API so that you can create services and publish it on your local network and NSURLAuthentication is enhanced with Kerberos single sign-on and iCloud credential syncing.
OK, so Paul Danbold is our Core OS Technologies Evangelist, he is happy to field any questions.
The Foundation Class Reference is being updated with documentation for NSURLSession and the Developer Forums will be available to answer your questions, they will hang out there and answer questions.
There's some other sessions I want to point you out though, yesterday was this Managing Apple Devices session, that and the Extending Your Apps for Enterprise and Education Use session is where you learn about Kerberos Authentication and how that's handled.
Yesterday's talk on What's New with Multitasking is very important and relevant to this discussion.
Dave Chan showed how to use NSURLSession in response to background notifications in order to get work done in response to, you know, a server pushed token.
Nearby Networking with Multipeer Connectivity follows this session and we're going to talk there about more about how to do use NSNetService to create server use and publish service.
And then sounds like What's New in State Restoration is relevant because we want to know when your application is re-launched, how to update your snapshot and have a nice live experience for the user.
So thank you.
[ Applause ]
[ Silence ]