Frameworks • iOS • 50:40
Come hear the advancements in document handling in iOS 8. See how easy it is to use the new Document Picker UI. Learn how to share documents between apps, and even provide documents to other apps from your custom data store.
Speakers: Johannes Fortmann, Mike Hess
Unlisted on Apple Developer site
Downloads from Apple
Transcript
This transcript has potential transcription errors. We are working on an improved version.
Thank you. I'm Mike Hess. I'm a software engineer on the iOS Apps and Frameworks team, and I'm here with Johannes Fortmann to talk to you about building great cloud documents-based applications. So here we go. We've made some important changes to iCloud. First, the iCloud daemon has been completely rewritten on top of CloudKit. We're calling it iCloud Drive. If you're interested in learning more about CloudKit, I encourage you to attend their sessions and labs.
Second, we've added Windows support to iCloud. Now your users with Windows devices can access and modify their documents on their Windows devices. Third, we've added an iCloud folder into Finder. Now your users can add whatever documents they want into their iCloud folder in Finder and organize them however they see fit.
Fourth, we've added access to this iCloud folder from within your iOS apps. We'll get into this a little more later. So, what are we going to cover here today? We're going to start off by talking about some of the best practices of accessing your documents in the cloud. Then we're going to move on to talking about how to discover and list your documents in the cloud.
Next, we're going to talk about displaying thumbnails in your UI when you're listing your documents in the cloud. Then, we're going to talk about accessing documents from outside of your apps container such as the shared iCloud folder. And finally, we're going to talk about providing document storage to other applications from within your app. So, what is a document anyways?
We're going to define a document here as a single standalone entity, and it's understood by the user as a single standalone entity. A user might want to modify it, or give it a name that's meaningful to them, or send it via email to one of their friends or colleagues.
There are some documents which we all sort of understand are documents: a keynote document or a numbers document or a pages document are clearly documents. But we're also going to consider something like a chess game to be a document, for this presentation. A user might want to save the current state of their chess game and email it to one of their friends so they can pick up where they left off against some hard AI level. So, we're going to consider a chess game to be a document.
Now, let's talk about dealing with your documents in the cloud. So, it's important, when you're dealing with your documents in the cloud, to use file coordination. There are several reasons for this, but one of the main ones is to avoid data loss. You may have the simplest single-threaded application in the world, and you may think that you're the only one reading from or writing to your documents, but once you add the iCloud daemon into the mix, that's no longer the case, so use file coordination. Let's take a quick example of this.
Say your app is doing proper file coordination. You'll write your changes to disk, the iCloud Drive daemon will pick up those changes and push them up to the cloud and down to all the other users' devices. Everything's working properly here. That's what you want to have happen. Now let's say you're not using proper file coordination.
You may be writing your changes to disk, but iCloud Drive may also be writing changes at the same time for that same document. This could result in a corrupt document which the iCloud Drive daemon will again push up to the cloud and down to the other users' devices which results in data loss everywhere, so use file coordination; it's very important. There's good news though. UIDocument makes things simple.
UIDocument and NSDocument, on OS X, does all the heavy lifting for you. It takes care of file coordination. It also uses background queues to prevent the file coordination from blocking your apps UI, and UIDocument provides you with several high-level APIs for whatever use case you might have. Let's take a quick example like reading a document from disk with UIDocument.
So, at the highest-level UIDocument does all of the file coordination for you, and in addition reads your document from disk. If your document is a file you'll get an NSData object, which is the contents of your file on disk, and if the document is a package, you'll get an NSFileWrapper object, which represents your package on disk. You just have to override the LoadFromContentsofType method and then display the contents of the document to your users.
At a slightly lower level UIDocument still does all of the file coordination for you, but this time you would an NSURL back which is the location of your document on disk. You then just have to read the document and display it to your users. At the lowest level we have an option that's really provided only for hooking. If you override the openWithCompletionHandler method, you should really invoke super, and implement one of the other two methods. You can override this method though if you want some custom application behavior when UIDocument would be doing the file coordination to read the document from disk.
New in IOS 8, we have some asynchronous file coordination APIs. So, the existing file coordination APIs were completely synchronous. That means you would have to do your own background queuing to prevent file coordination from blocking your app. That can be a little bit tricky to do. So, we have some new file coordinator APIs for asynchronous file coordination, which is the coordinateAccess WithIntents method.
We also have a new corresponding class which is the NSFileAccessIntent class which essentially just contains a URL and some options for your intent of coordination. You pass these in an array to the coordinateAccessWithIntents method to do your file coordination operations. Let's take a quick look at that in some simple code. So, this code might be if I want to copy a document from one location to another.
As you can see I allocate a source intent to read the document where it currently exists on disk. I then, allocate a destination intent for the location that I want to copy the document to. I pass these to the file coordinator method of coordinateAccess WithIntents, and at some point in the future my accessor block will be called on the queue I provide.
I then just have to do my operation in my accessor block. Now, it's important when you do your operation in your accessor block to use the URLs that are attached to the NSFileAccessIntents because they may have changed while you were waiting for your coordination. Now let's move on to discovering and listing your documents in the cloud.
So, the way to discover and list your documents in the cloud is through the existing NSMetadataQuery APIs. Now, in previous versions of iOS NSMetadataQuery has been slow to pick up your local changes like creates, deletes and renames; let's take a quick look at this. So, let's say you have your app, you have a couple of documents in your apps container, you also have a couple of NSMetadata items from your NSMetadataQuery which correspond to those documents on disk. Now let's say your app creates a new document on disk. There might be a long delay before NSMetadataQuery updates and gives you a new NSMetadata item corresponding to that newly created local document.
New in iOS 8 NSMetadataQuery is easier to use directly with stitching. Let's take a look at that. Now let's say your app creates this new document on disk, and is using proper file coordination. This only works if you create the document using proper file coordination. We actually have a hook in your file coordination access which will update the NSMetadataQuery quickly and automatically to create a new NSMetadata item to update your app. That means that you no longer need two data sources to show your app's UI, one from local changes and one for cloud changes. You just need NSMetadataQuery. [applause] Thank you.
Also, NSMetadataQuery can list non-local documents. You may want to display some file system attributes about those documents though, to display in your UI when you're listing your documents. We have a new NSURL API for you, which will let you get file system attributes about those documents, which may or may not have their content available locally. The way to do this is with the NSURL method, getPromisedItem ResourceValue:forKey.
If you want more than one file system attribute we also have a bulk method, which is the promisedItemResource ValuesForKeys. You don't need to be under file coordination when using these methods for listing your documents. Also, if you are under file coordination, we have some new file coordinator flags for dealing with metadata.
The key difference with these methods is that the content with these flags that you pass through your file coordinator is that the content of the documents does not need to be available locally when you are doing file coordination using these flags. Now let's move onto document thumbnails. So, we think the best user experience when you're listing your documents in your app is to show document previews. This gives your user more context so that they can quickly identify which document is meaningful to them at that point in time. As you can see in this pages app, we have document previews, which lets your user quickly identify which document is which.
Now it was possible to show document previews previously, but it required a custom implementation. New in iOS 8 we have some new file system attribute keys for you to display thumbnails in your app. The main way to do this is with the NSURLThumbnail DictionaryKey. If you call this on your document using the getPromisedItem ResourceValue :forKey method you'll get a dictionary which contains your thumbnails, which you can display on your UI. The only key in this dictionary right now is the NSThumbnail 2024x1024SizeKey, which corresponds to the UIImage or NSImage which you can then just display in your UI.
Now onto saving document thumbnails. So, the easiest way to save thumbnails is through UIDocument. If you override the fileAttributesTo WriteToURL :forSaveOperation method and have it generate a UIImage which is your thumbnail and return it, UIDocument will automatically write the thumbnail to disk for you, and then the iCloud daemon will go ahead and pick up those changes and push them up to the cloud. Alternatively, if you're not using UIDocument you can save your thumbnails manually using the existing NSURLsetResource Value:forKey method, but you should really be under file coordination when you invoke this method.
On OS X thumbnails are actually generated for you automatically. However, if you have a custom document format you'll need to let Quick Look know how to display thumbnails for your documents, so you'll need a Quick Look plug-in to generate your thumbnails. Now let's move onto to discovery documents outside of your apps container.
Now, in previous version of the OS, it's been difficult for your users to access documents outside of your apps container from within your app. Let's take a look at how they might do this previously. So, let's say you have your app, you have direct access to all the documents in your app's container; there's no problem there. But let's say your user wants to open say document three from within your app.
How might they go about doing this? Well, one way they might do this is they would have to launch the other app, then using the UIDocument interaction controller make a copy of the document from the other apps container into your app's local container. Only then could they read the document from within your app.
We think a better user experience is if your app can just access those documents in the other apps container directly. So, if you have your app again, if you can just open those documents directly, the user is happy. So, we think that's a better user experience. New in iOS 8 there's a way to do this with a UIDocumentPicker ViewController. This allows your users to discover documents outside of your app's sandbox and lets your users grant your app permission to access and modify the documents that they have chosen.
Now, to have your apps container show up in the document picker you have to opt-in by marking your container with a NSUbiquitousContainer IsDocumjentScopePublic to be "yes" in your info plist. I have a great new UI -- we have a great new UI here, which you can display in your app for your users to choose documents, and I'd like to show you that now with a quick demo.
Okay. Let's go ahead and launch my app. Yeah, the app I've written. It's a simple text-editing app. So, as you can see, I'm using NSMetadataQuery to list only one document in my container right now, but I'm using NSMetadataQuery without file coordination to list my documents and display a quick simple preview of the documents. Now let's go ahead and launch up the document picker.
So, this is our new document picker UI. As you can see there are several containers listed here but I also have a document which lives in the shared icon folder which is listed alongside my containers. Now I can switch to list view here; there's a bunch of stuff I can do, sort by name, tag, state, etc. Now, let's go ahead and like drill down into this text edit container, and select a document from the text edit container.
So, now I have opened the document which actually lives in the text edit container. I have not made a copy of this document. This document still exists in the text edit container but now that I, as the user, have granted my access to it I can edit and access it in the text edit container.
Let's go ahead and X out of this. As you can see, now that I've granted my app access to this document it has now updated in the NSMetadataQuery and I can list it alongside the other documents in my app. I've also annotated it, if you can see with a text edit name, just to tell my user that it lives in the text edit container. Let's take a quick look at this in code.
So this is basically all the code I had to write to display the document picker. All I have to do is allocate the document menu view controller and pass it on array of the document types that I'm interested in. I have a simple text-editing app, so I only pass the plain text UTI as the documents that my app can access.
I then just present the view controller and then implement these two simple delicate methods, and finally when the document -- when the user picks a document of a given URL I just load it and display it to my users. It's super simple. Now if you noticed my app did not actually show up in the document picker. That's because I haven't set my container to be a public container, yet. Let's take just a quick look at how to do that.
So, if I open up my info plist here, drill down into this. As you can see my document scope is set to be not public. All I have to do is set this to "yes" and then bump the bundled version so that the document picker knows that I have made a change to my info plist, and then my app will be displayed in the document picker so that other apps can get access to my documents. All right, so quick summary. We've just shown you how easy it is to display the Document Picker inside your app, and how easy it is for users to grant your app access to documents in other apps' containers such as the shared iCloud folder.
We've also shown you how easy it is to make your container show up in the UIDocumentPicker just by setting a flag to be yes and then bumping your bundled version. With that I would like to Johannes Fortmann to the stage, who is going to talk to you about some of the key principals behind the Document Picker. Please welcome Johannes to the stage [applause].
Thank you, Mike. Hi, I'm Johannes from the UIKit team, and I would like to talk to you about some of the main differences between external documents and documents that may live in your container. As you know, your application right now has access to its own container only. So, you're able to read and write the documents inside your own container.
And as you have seen in Mike's demonstration for other documents what we do is once the user has chosen this document we save a so-called document reference into your container. This document reference will then go and point to your external document. To ease this new concept into your application we provide a few new features and attributes on the NSMetadataQuery.
You are probably using the NSMetaDataQuery with the UbiquitousDocuments Scope right now to list the documents that are inside your container, locally. And even if the user has granted your application access to a document outside of your container -- even if the user has gotten your application access to document outside of your container, we will still continue to merely list the documents that are local to your container as long as you don't pass a new scope which is the UbiquitousExternal DocumentScope.
The UbiquitousExternal DocumentScope ensures that you've got an NSMetadata item that corresponds to the file references that the user has extended to your application container. Now, these new NSMetadata items are effectively just like the old ones. They also have an NSMetadata item URL key and this NSMetadata item URL key will point to this -- NSMetadata item URL key will point to the URL that your document is actually located at. That means that if your app is using the NSMetadata item URL key right now to access the file directly that will still work even with the document reference.
You can pass the return value of getting this key directly to, for example a UIDocument, and use that URL to directly access the external document. Now, of course sometimes that is not actually what you want to do. Sometimes, what you're interested in is not the actual document backing this reference, but rather the reference itself. For example, you may want to display the reference inside a folder in your application's container, in your UI, or you might even want to allow the user to move these references around inside their folder.
For that we provide a new key, and this one is actually new on iOS 8, the UbiquitousItemURL InLocalContainerKey. This key points to the actual reference inside your applicant's container, so the user can use the file that is at this location to move it around. Now, there are a few other keys.
It may be useful for you to know whether a file that has been returned by the NSMetadataQuery is actually external to your application or not -- sorry, to your application's container. And for that we provide the IsExternalDocumentKey, which will return "no" for local documents and "yes" for external documents.
And as you've seen in Mike's demo he showed a little badge or text a label to inform the user that the document that he's shown that popped in there was actually not from the local container but rather from Text Edit, and to enable you to do that we have the container display name key, the container display name key is a localized key that is fit for display DOS and for example would if you extended a document from Text Edit would show Text Edit's name.
All right, so, we've got these document references, but why do you even need these? So, the main reason is for security. We do not generally allow any app to access any other app's container. Only the Document Picker can do that. The Document Picker is running out-of-process, so it's not -- it is able and has the sufficient entitlements to be able to list all of the document containers. And the only way to get a document inside of your application is to use the Document Picker.
To that -- for that purpose, we return a so-called security scoped URL and if you've used the sandboxing mechanism on OS X you may already know this concept of a security scoped URL. You get a NSURL, which has a tiny bit of information attached to it, that informs the kernel, and of course the owning app, that in fact the owning app is allowed to access this document, and is allowed to for example modify it as well.
Now importantly, if you naively were to save this URL, for example you would serialize it into a string and then de-serialize it out of the string, you would lose this security scope. And that is not something you want to happen because of course the security scope is what you use to access this URL.
Of course, you need a way to get back to the scoped URL, and the document references feature is providing one of the ways to get back to these URLs. If you get a NSURL from the document reference this NSURL already has the security scope attached, so you can use it with your document or with the start accessing and stop accessing security scoped resource methods on NSURL - but I strongly suggest that you use UIDocument because that does all of this for you; for example, load the contents off of the file backed by this URL.
Now, sometimes enumerating your documents is not actually what you want to get back to the document. For example, one thing you might be using is state restoration, and in state restoration of course what you want to do is pop the user back into the UI that they saw before.
So, you instead of enumerating files that the user had access previously, what you want to do is access a very specific file. We offer a mechanism to do that for you, which is a bookmark. The bookmark is also possibly known to you if you've used it with the sandbox on OS X, and the bookmark and codes the security scope alongside the URL so you can use the bookmark to get back to the security scoped URL. We offer API, which already exists.
The bookmarkDataWithOptions API is used for, by you, on a NSURL instance to create a bookmark that you can then save. It's basically opaque NSData blob that you can then save into a state restoration archive, for example. And of course its counter-part is a class method on NSURL. The URL by resolving bookmark data which we can then use to resolve this bookmark into a NSURL that has the scope attached.
All right. Now, Mike showed you the UIDocument picker view controller in the so-called open mode. In open mode what we will do is indeed create a bookmark and a corresponding security scope URL, hand you back the security scope URL and of course place the bookmark, the reference document inside your app's container.
Now, sometimes that is not what you want to do, actually. For example, you may have an application that does not instead of opening specific documents, may also aggregate documents, Keynote, for example would be one of these applications, in which you, for example, might want to open an image from an application to insert it into your presentation.
You don't want to maintain a persistent reference to that image, but instead want to copy this image into your presentation as one piece. And we also support a mode for that, it's the so-called import mode. In import mode will not create a bookmark, but instead we'll copy the file to a temporary location.
You will of course still be granted access to this temporary location, but the file is not persistently referenced by your application. After your application terminates for any reason we will clean out the temporary location and you will no longer have access, so you have to make a copy soon after you get your delegate call back to actually hang onto the document.
All right. This is reading documents and it is of course a very important part, but equally as important is of course writing document and creating new documents. Now, as I've mentioned you will not have general access to containers outside of your app's own container. But of course you can write into that container, so -- or possibly into a temporary location.
So, to create a new UIDocument that is -- sorry, a new document on disk that is exactly what you want to do. You can then use a special document picker mode to move that document outside of your app's container, but again the user chooses where to move the document.
Let's have a quick look at how that works. You would, of course, you already have a document, Doc 3 in this case, and you use the initWithURL method on your document picker with the URL of your existing document to allow the user to choose a new location. The user now chooses a new location, and we move the file into the new location.
We will return a document reference to you, so you still maintain access to the document. And this URL is effectively exactly like one that has been returned to you by the open mechanism, so you can enumerate this new document preference in your NSMetadataQuery. Now of course sometimes that is exactly not what you want. You don't want the reference. So, we also have an expert mode, which allows you to forego the entire reference thing. In that case we will make a copy of your document into another app's container and that is basically it.
Okay. Let me give a quick summary of how to use document management here. We've seen that you can use the document reference mechanism to enumerate documents that have been previously used by, or granted access by the user. We've also seen that you can use bookmarks for state restoration and we've also shown you quickly how to use the import open and export and move modes. And all of these of course play together to enable your user to access all of their iCloud documents, not merely those that are inside your folder.
But you noticed I said all of your iCloud documents here, and, of course, your users may have different locations for storing their documents. For example, you may be part of an enterprise that has their own storage management system, and, of course, it would be grand if you could grant your users access to those documents as well. And for that we are introducing a new feature, the so-called Document Provider Extensions.
Now, what is a Document Provider Extension? A Document Provider Extension is an alternate way for you, or a third party, to provide document storage. From the host application's perspective this works exactly the same way as the pre-existing iCloud storage location. The user is able to select one of these storage locations from the Document Picker, and they can use these storage locations in the exact same mode so they can open documents and move out documents to the storage locations.
We implement these using two different, separate extensions, the first of which is the so-called Document Picker Extension, which provides a UI view control subclass that is effectively free form; that the user can use to choose a document from your storage location, or from, of course, from someone at the storage locations. This UR Document Picker subclass is displayed as part of the document picker view controller, so it's effectively contained inside one of these view controllers just like the iCloud Picker is.
There is also a separate second extension, which is the so-called File Provider Extension. The File Provider Extension is a non-UI extension, which deals with actually providing the files. The usual use cases where you want to provide files would be, for example, ensuring that a file on disk is current, uploading a file that has been changed by the user, or enabling us to identify a file, so the user can save, or the user's app can save a bookmark for state restoration.
The file provider extension -- access to the file provider extension is modulated through file coordination, which means that all accesses that go through file coordination will automatically do the right thing with regards to providing access to the file. This is another important case where you absolutely must use file coordination or everything else -- everything will just not work.
All right. Let's have a quick look at how the data flow works with a File Provider Extension, specifically when reading a file from disk. Let's say you have a host app and this host app is used by the user who is trying to actually open a document, in this case. So, the host app, through some UI action, is calling the initWithDocumentTypes inMode method on the UIDocumentPickerViewController, and now the Document Picker -- well, the user inside the Document Picker selects a third-party Document Picker extension: yours.
We instantiate your UIDocument Picker Extension and send it prepare for presentation in mode call. Now, this method is called with the mode that the user has actually selected, and at this point you want to probably display a View Controller that corresponds to the mode that the user has chosen.
For example, for the open mode you would want to display a view controller that allows the user to pick a specific document, and of course for the move out mode you will want to display a view controller that allows them to select a location instead of a document.
All right. The user now goes ahead and uses your UI to select a document at which point, after the user has confirmed their intentions, you have to determine which location in the file system you want to store this document in. You can then call the dismiss grant access -- the granting access to URL method on self, well, that is your Document Picker View Controller Subclass, and thereby inform us about your intention to actually the user to access this URL.
The document picker will then call the document picker didPickDocument AtURL method on its delegate to inform the user app that the user has just picked this document. Now what the user is probably wanting to do is to read the document at this location. It will use the NSFileCoordinator methods, for example, coordinateReading ItemAtURL and its file coordinator that it should ensure that the document is actually present. NSFileCoordinator will call out to your file provider extension, that's your tiny non-UI extension, with the startProvidingItemAtURL method.
This method takes a completion call back which you can call once you're sure that the item at this specific location is actually current. So, once you call that completion call back on -- sorry. Once you call that completion call back the file coordinator will know that it is now able to unlock the file and it itself can call its accessorBlock. And now inside your accessorBlock the user application can use this UR document like it sees fit, for example, using data with contents of URL to be able to read the file.
Let's take a quick look at how security and persistent file access works for document providers. Unlike the iCloud document provider, which saves the special document reference inside an iCloud container the document provider extensions don't take part in the document reference mechanism. This is because, of course, in this let's say we're in an enterprise setting, our enterprise administration has decided that they do not want to use iCloud, but of course we still want this document provider extension mechanism to still work because our enterprise has given us an application that can be used to access the files on the enterprise's file server. So, it's no good to use iCloud in this case, of course, to get back to your document preferences. But, of course, the bookmark mechanism will still work.
To that end, the file provider is able, or has to be able, to resolve or resolve into a file URL and the other way around. Now for security purposes we have an isolation layer that saves the state information about which application has been granted access to which identifier -- inside which file provider, and this is also something that we use these identifiers for.
Let's have a quick look at how a bookmark is created and resolved by a Document Provider Extension. Let's say we have our host app and the host app is, for some reason, going into the background and just wants to save its state, it will call the bookmarkData WithOptions method on NSURL, and NSURL will call the persistent IdentifierForItemAtURL method on your file provider extension, which can then return a persistentdentifier. This might be a database key or it might be something much simpler; it depends on the actual way that your file provider is actually accessing files.
Now, at some point it will return the Personal Identifier, which is just a freeform NS string to the NSURL, and NSURL will package that up and return it as the opaque data blob, that has the bookmark data. At this point our user app can go and save its state, and, for example, get terminated in some way, for example, the user reboots their device.
Now, at some point later the user is reopening their app, the user app is doing state restoration, and in the process of doing this is calling the URL by resulting bookmark data on NSURL. We hand the identifier back to your file provider which can in the URLForItemWith PersistentIdentifier method and it can then resolve this identifier into a NSURL on disk.
Now, soon after, we call the providePlaceholder AtURL method which you can use to provide a small placeholder that can be used in correspondence with the previously discussed getPromisedItem ResourceValueby theUser app to merely get Metadata on this file. But what it can also do at this point eagerly download the file. We will at least ensure that you are providing a placeholder though.
You pass the NSURL off the file on disk back. The NSURL method can now return this NSURL and the host app can use the getPromisedItem ResourceValue to merely read metadata or use FileCoordinator AP on the NSURL to access the file. Well, no matter what you have chosen that we will at least call you to ensure if the user uses file coordination in this case to load the actual data from this document to ensure that the file on disk is current.
All right. We've seen how reading works and how getting back to your documents works. Let's have a quick look at how writing files works. In this case, the user is using, or the host app is using the file coordination API to actually write data to disk. So, it would do a coordinated write to the file inside your storage apps folder. The file is now changed inside your storage apps folder.
At some point very soon after, but importantly to note not in a blocking way, so the file coordination will have succeeded by this point, we will call itemChanged AtURL on your file provider. At this point your file provider can go and for example initiate an upload of this file, or at the very least mark it as being dirty and needing upload, so you don't accidently overwrite it at a later point. All right. Let's have a quick look at how that works.
What I've done is I've built a very small sample project using the template that comes with xcode, which is very nice, because it provides you with almost everything you need at the start. We can use the target here and use the application and get extension template for the Document Picker, and basically choose a name here and it'll set up the two different extensions.
Inside my project I just have the two different extensions, one folder here for the actual picker. I'm doing a text snippet picker to go with the text display app that Mike showed. And inside this I have a whole bunch of files which are basically, well, classes to display some sort of picking UI, but the important part is my subclass of UIDocumentPicker ExtensionViewController here.
And inside this subclass the important parts are the prepareForPresentationinMode method - let me make this big so you can see this - and in this PresentationinMode method what I want to do is basically display a specific, in this case I'm using a collection view controller to display a list of documents, and I'm displaying this.
And all of my picking actually is not handled by my DocumentPicker ViewController, but by a subclass. Of course, I use a delegate pattern to get back to my main class once the user has picked a document and we'll call this method here and inside this method all I have to do is call the dismissGrantingAccesstoURL with the file URL that I've previously written out.
Now, the document file provider here is very simple in this case. The interesting method for this demo is the startProvidingItem withURL method, which I implement to ensure that the snippet at this URL is current, and then call the Completion Handler. Let's have a quick look at how that looks on the machine.
All right. I've got my demo app here, which is basically, since I started from the template, just an empty app. So, instead I'm going to pop off the Document Picker and you notice I don't even have any documents in my iCloud account, but when I pop up this Document Picker menu here, I see a list including the iCloud document picker and my SnippetPicker. And if I pop up the SnippetPicker what is displayed is my SnippetPicker View Controller and I can use that to pick any of these documents or Snippets in here.
So, when I pick these with the exact same sample app that Mike showed you I'm able to access these Snippets from my little document picker app. Now, when you use the seed one to try this out, note that this Snippet that the document picker you will create will not show up by default, so you can use the little locations button in the navigation bar of the iCloud Document Picker. It has a little more pop out where you can enable the Snippet Picker. All right. Now let's switch back to slides.
Cool. To summarize the demo, we've got an Xcode template to get you started with the document picker mechanism. The Document Picker, or a Document Provider will show up right next to the iCloud picker if the user installs them. And we also have sample code available on the Session Home Page, that will enable you to quickly test this out. The sample code is basically a little test app that we wrote to be able to display each of the document picker modes.
Cool. So that's Document Providers, and that almost concludes the session, but I have a little bit of information for you -- to inform you how since we have this new Cloud Drive mechanism, how the migration story is for that. On iOS 8 the users can either choose to, once it comes out, choose to use the old iCloud Documents mechanism, or to migrate to iCloud Drive.
On OS X Yosemite we do not provide the backwards compatibility for the old iCloud documents mechanism, so the user has to either choose to migrate to Cloud Drive or they will no longer receive the updates across their devices. Of course, they can choose to migrate at a later point, at which point the upgrades resume. And of course after an account is migrated to iCloud Drive only the devices that are actually using iCloud Drive will propagate changes between each other.
For US developers this is important to know because even though the current Seed Build that you have in your hands right now is automatically using iCloud Drive, the actual new features - and thus you can easily test all of this out - the new features that we've presented in today's presentation will only be available if your user is using iCloud Drive.
So you have to be aware of this possibility in case they have not actually chosen to migrate. All right. To summarize, if you're just taking one thing away from today's session it would be that you should use file coordination for document access. Without using file coordination, none of these mechanisms can work, and you will probably be at some point experiencing data loss on the machines of your users; which of course is extremely bad.
We've seen how to discover and display files not only in your own container, but also using the UIDocumentPicker which allows you to access files outside of your applications' containers. We've given a quick overview on how to use document provider extensions to be able to integrate your own company's storage system into the whole document access mechanism. For more information I would like to guide you to Dave DeLong, our App Frameworks Evangelist and also Jake Behrens who is the UIKit specific Frameworks Evangelist.
We have some neat documentation out. There is a brand new iCloud for Developers guide and we also have guides for the Document Picker, and of course also guides for the extensions mechanisms. We also have the Apple Developer Forums where our developers hang out and will answer questions. Related sessions: there was a very nice session on introducing CloudKit. If you're interested in the technology behind the new iCloud Drive mechanism that powers all of this.
This session is of course not entirely necessary if you merely want to store your documents because the CloudKit mechanism is entirely transparent from the document storage perspective. We also have had sessions on creating extensions for iOS and OS X, and with that thank you for your time and I wish you pleasant rest of the week and a nice bash.
[ Applause ]