Building Great Document-based Apps in iOS 11

Session 229 WWDC 2017

Document based apps have never been better with the new consistent system-provided user interface for opening and creating documents. This session will go into detail of how your document based app can leverage this functionality to provide a great user experience. See how to customize the UI so it fits perfectly inside your app. Get details about making your documents look their best with the new QuickLook APIs for generating thumbnails and for showing custom previews of your own files formats.

[ Applause ]

Hello, everyone.

I hope you're having a great WWDC.

Welcome to Building Great Document-based Apps.

Today we are going to talk about all the new features of the Files app and how to integrate them in your app.

First, let's talk about the Files app.

One of the biggest features of this app is that it gathers all the cloud vendors in one place.

This is done thanks to the new file provider extension.

All the cloud vendors that use this file provider extension will appear next to the iCloud drive on my iPad in the sidebar.

If you want to know more about this extension, we invite you to check out the File Provider Enhancements session tomorrow at 11:00 a.m. There are two file providers by default in the system.

The first one is the iCloud Drive provider.

It will show all the files inside the iCloud drive folder of the user as well as all the files in the Cloud container of all the applications in the system.

The second provider is the on my iPad provider.

It will let the user leverage the storage of their devices.

It will show the content inside the Documents folder of the app container.

If you want your app to be part of this local storage provider, your app needs to be a document-based app or support File Sharing and Opening Documents In Place.

As I said before, we are going to be showing the documents inside the, the files inside the Documents folder.

So please keep the content of this folder clean.

You should only have the files that matter to the user.

Also, you have to keep in mind that these files won't be synced across multiple devices but still will be part of the iCloud backup.

Now I would like to talk about the new Recents view.

This view will show all the documents that have been recently opened, imported, and modified.

Also, it will show all the documents organized by tags and all the documents that are shared with other people.

Tags are a great means to organize files.

And in iOS 11, there's new tagging UI that will let the user create new tag and manage their tags.

Tags will be synced across multiple providers and they will be also synced across all your devices.

The last thing The last feature I would like to talk about in the Files App is the Recents Popover.

The user will be able to present this popover when performing a long press on the Files App.

This [inaudible] will show all the recent documents and the user will be able to open them with just one tap.

It will also let the user import the document into any application using the new Drag and Drop gesture.

I'm sure now you want to have all these great features in your app.

Throughout the last release cycles, we've received very many requests from you.

You want to have a unified UI for file browsing.

You want your app to be able to access any file from other apps in the system.

You don't want to write more code in order to adopt all the cloud vendors that are already part of the system.

And you want to have deeper integration of your custom content types throughout system.

Well today we are going to view some new API.

I will tell later how we've done so far with those requests.

First, I would like to talk about the new document browser API.

This year there's a new class, the UI Document Browser View Controller.

I know it's a mouthful, so from now on I will call it the Browser VC.

Together with this, there's a new Xcode template that will let you create a new document-based application from scratch.

And also the UI Document Picker will get some of the features of the Browser VC.

So now let's first talk about the Browser View Controller.

This view controller will provide your app the same feature set as Files app.

In fact, Files is just a very thin layer on top of this Browser View Controller.

With this view controller, you won't have to write more code in order to integrate any cloud storage provider that supports File Provider.

Also it will support appearance customization to make it look like your app.

And by using this view controller, your app will get the Recents Popover that we saw before.

Spotlight plays a key role in this Browser VC.

By using this view controller, all the metadata of your document will automatically be indexed in Spotlight.

If you need to have further integration, you will have to register your own CS Searchable Items.

Now there will be two CS Searchable Item in the system as in order to duplicate them, the Browser VC will use a content URL of this CS Searchable Items.

So you have to set it properly.

If you want to know more about Core Spotlight, there's a session at 4:10 p.m. today.

At Apple, we deeply care about our user's privacy.

Because of that, we built the Browser View Controller with privacy in mind since the very beginning.

When the user installs your app, you will only have access to all the documents inside the app container.

You will be able to import and create new documents but only the default safe location which will be a [inaudible] for you.

So how are you going to access to a file in any other place in the system?

Well, you will do it via user interaction.

The Browser VC is running in a different process.

And once the user taps on a document, the Browser VC will forward to your app the access of that document.

And now, let's take a look at the UI Document Picker View Controller.

As I said before, we'll get some of the features of the Browser VC.

For example, the Browse View and the Recents View.

Also, it will support opening and importing multiple documents at the same time.

If you want to support it, you need to set the allows Multiple Selection to true.

In order to support multiple documents, we are deprecating the document picker with Pick Document At URL delegate method in favor of a delegate method that support multiple URLs at the same time.

Also this year, we are deprecating the UI Document Menu View Controller in favor of the UI Document Browser View Controller.

And now, we've seen an overview of the browser APIs.

Let's take a look at how to make use of this UI Document Browser View Controller in your app.

So first things first.

You will have to configure the Info.plist.

Here, you need to set the UI Supports Document Browser key to yes.

This will tell the system that your app is a UI Document Brower based application.

Then you will need to declare the content types that are supported by your app.

And this is important because the Browser VC will use this content type in order to know what files to display in your application.

It's important to note that the UI Document Browser View Controller needs to be the root View Controller of your app.

It won't work otherwise.

As I said before, the Browser VC supports appearance customization.

By default, it will look like this with a white background and a blue tint color.

There are two properties that you can use in order to customize it further.

The browser Interface Style which has three modes, dark, white, and light, and tint color.

If you use a dark style and an orange tint color, your app will look like this.

So now that we configured the Browser VC, the first thing your app will have to support is Opening Documents.

So let's take a look at how it works.

First, the user will tap on one of these documents.

Here, the Browser VC will fetch and download the information of the document.

And once the document is ready, it will forward the access to your application and call the did Pick Delegate method.

Here, you just need to load and present the document.

When opening documents, the Browser VC will give your app persistent access to that URL.

Now, if you want to restore it, it's not enough to store the URL.

You need to store the bookmark data associated to this URL because this is the piece of information that keeps track of the URL access.

The code to Opening Document looks like this.

You just need to implement the document Browser did Pick Document URLs and present the view controller for the document.

Like the UI Document Picker, the Browser VC supports opening multiple documents at the same time.

If you want your app to support this, you need to set the allows Picking Multiple Items to true.

Now that your app is able to open any file in the system, the next thing is to be able to create new documents.

There are two places where you can create new documents.

The first one is the Recents View.

If the user taps the Create button here, it will create a new document in the default safe location of your app.

If you tap the Create button in the Browse View, it will create a new document in the current location of the Browse View.

Now let's take a look at the workflow.

Once the user taps on one of these Create buttons, your app will receive an import handler.

Now if you already have the source URL, you can call the import handler.

If not, if your app needs to show some template chooser in order to know what source URL to choose, now is the moment.

You present a template chooser and call the import handler.

The import handler will move that file to the provider.

And once the file is in the provider, it will call you back with a succeed delegate method.

Here, as for the open case, you just need to load and present the document.

Now the import operation can fail for many reasons.

And if that is the case, you need to handle the error and present some UI to the user.

Now let's take a look at how to code this.

First you need to implement the document Browser did Request Document Creation.

Here, as I said before, you can optionally present a Template Chooser.

Now in this example, the present Template Chooser will call us back with the URL that the user picked for the template.

And it will tell us if the user canceled the document creation.

Once we get the URL, we just need to call the import handler with a mode.

There are two different modes: copy and move.

If the user canceled the document creation, we still need to call the import handler with nil as the URL and none as the mode.

This is important.

This will tell the Browser VC that the creation operation is over.

Once the document is fully imported, the document Browser did Import Document At source URL to Destination URL will be called.

Here, you just need to load and present the UI for the document.

As I said before, the import operation can fail.

And if that is the case, the Document Browser failed To Import Document URL will be called.

Here, you need to handle the error and present some UI to the user.

Now we are dealing with documents that are operated by different processes, different apps, and different devices at the same time.

And because of that, it's important to use NS File Coordination and NS File Presenter in order to avoid risk conditions between these processes.

Now because the document is outside your app container, the Browser VC is using Security-scoped URLs, which means you have to start and stop accessing that URL in order to have the right to write and read the URL.

We highly encourage you to use UI Document.

By using it, you will get File Coordination, File Presenter, and Security-scoped URL support for free, as well as other features like Autosave.

If you want to know more about UI Document, please take a look at the Building Document-Based Apps session from WWDC 2015.

And now I would like to introduce my colleague Raffeal to give you a demo on how to use the UI Document Browser View Controller in your app.

Raffael [ Applause ]

.

Thanks, Pau.

Good morning, everyone.

So now that you've got to know the API of the new UI Document Browser View Controller, I would like to walk you through and show a demo of how easy it is to build a great document-based app for iOS 11.

We're going to build a very simple particle editor with a particle system on the left and an inspect on the right side that allows you to customize some properties of the particle system.

Now each particle system comes within one document and, therefore, using the UI Document Browser View Controller is a perfect choice for our applications.

So now let's just switch to Xcode.

Xcode 11 comes with a new template for document-based applications.

Let's try it out.

Going to call it particles and create the new application.

Now once instantiated, this template comes with everything you need to build a document-based application from scratch.

First of all, the Info.plist of our target is already set up the way Pau mentioned it earlier with the right key.

Next, we have a Document Browser View Controller subclass that has all the code already in place that you might want to customize later.

It also comes with a view controller subclass, the Document View Controller which will be in charge of presenting the contents of our files.

Next, as Pau mentioned also earlier, we have the subclass of UI Document that acts as the model of our documents at runtime.

And last but not least, our storyboard is set up to have the Document Browser View Controller as the root View Controller already set up and the Document View Controller ready to be instantiated when we create new files or open existing files.

So let's just take a look at what we get just by launching this template in our simulator.

Now once started, we see the new Recents view with your recent documents that you might have created before.

Of course, we haven't created any files yet, so let's switch to the Browse view.

We see our Cloud storage vendors on the left side in the slide bar next to the new On My iPad storage.

We also see the Favorites and our Tags that are synchronized across all your devices.

In the middle of the screen, we see a large Create Document button that allows you to create new documents.

So let's click it.

Well, nothing really happens yet and that's expected.

That's because we haven't told the UI Document Browser View Controller yet what it means to create new files in our application.

So let's fix this.

Therefore, we switch back to our UI Document Browser View Controller subclass.

And as Pau mentioned earlier, when the user tapes the Create Document button, we'll get a call back to the Document Browser View Controller Delegate function did Request Document Creation With Handler.

Now what we have to do here is we have to give back a URL of the newly created file to the Document Browser View Controller.

Now in our situation, let me add a new particles file to our target.

We make sure that it's added to our target and finish.

Now at runtime, we just go ahead and obtain the URL of this added document via our NS main bundle.

Once we get the URL, we pass it to the input handler that we get from our delegate function.

And we perform a copy operation on the URL.

Now the UI Document Browser View Controller will get this URL and will do all the heavy lifting for you in the background like moving the file to the right location and processing the URL.

Once it's done, it will give us a call back to either did Import Document At source URL or failed To Import Document At URL.

Now if we fail to import the newly created file, since we want to be a good developer we should go ahead and implement proper error handling, for example, by presenting an error to the user.

However, if we succeeded, we can go ahead and present the document that we've just created.

Now let's say the user has picked an existing file, in that situation, we're going to get a call back to the did Pick Document URLs function.

Same here, we just go ahead take for example the first of our document URLs that we get and present it.

Now presenting a document in our app means instantiating one of these Document View Controllers giving it a document that we initialize with document URL that we want to open and then we just go ahead and present the Document View Controller.

Now let's take a look at the simulator again.

The app launches again.

We're in the Browse view and we can tap the Create Document button.

And the Document View Controller appears with details about the file that we've just created.

Once we are done, we can close the Document View Controller again to return to the root View Controller or Document Browser View Controller.

Now let me switch to a more advanced version of this project which has already all the code pieces in place to render a particle system on the left and an editor on the right side so that we can focus on the Document Browser View Controller related code parts.

Before I'm going to remove the app that we've just created to avoid any further conflicts.

Now this is still the same, it's still the same project.

It's based on the template that we've instantiated in the beginning.

Let me show you some additions that we made to our Particle app Info.plist.

First, again, the key to Document Browser View Controller is still set to yes, just the way Pau explained earlier.

But more than that, in the Exported UTIs section, we are creating a new UTI type for our Particles files.

We're going to give it a description particles.

We give it an identifier and we let it conform to the UTI types public data and public content.

That means our Particle files are a stream of data and they have a semantic of document files.

Now in the additional exported UTI properties, we defined that our files should have, whoops, sorry, should have the particles extension.

That means that any file in the system that has the .particles extension will be recognized as a file of our newly created UTI type.

So now that the UTI type is done, we can go ahead and tell our application that we're actually supported.

So in the Document Types, we just mentioned our particles file format again.

We identified the identifier and any additional document type properties.

We define our CF Bundle Type Role to be editor and the LS Handler Rank to be owner.

If you want to learn more about this, check the documentation.

So now the UTI types are properly set and that means that the Document Browser View Controller will make sure that users are only allowed to pick documents of our new file type.

It also makes sure that when you search inside the Document Browser View Controller, you will only see search results that make this UI type.

And last but not least, in any kind of UI document interaction control in a different application for Particle files, you'll see the action to open the file in our app.

So now let's take a look at our actual documents.

We switch to our UI Document subclass.

Now UI Document is quite powerful and we highly encourage you to make user of it.

As Pau mentioned earlier, it comes with a lot of great benefits such as autosaving, file coordination and NS File Presenter, Versioning, and much more and, therefore, the UI Document and the UI Document Browser View Controller are literally made for each other.

So let's take a look at what we are doing here.

Now the document represents the document at runtime.

So obviously since we are talking about Particle systems, it should have a reference to SCN Particle System.

Now the next thing we are doing is we're implementing saving and loading files.

Therefore, we have to overwrite the function's content for type and load from contents.

Now all we really have to do here is archiving [inaudible] an existing Particle system and that works because our SCN Particle System already conformed to NS coding.

So we don't really have to do a lot here.

We use a Keyed Archiver to archive the data or we use NS Keyed Unarchiver to unarchive an existing one again.

Now that's all you have to do about the document.

Let's take a look at the Document View Controller.

Again, that's the one that is in charge of presenting the contents of a document.

So obviously, before we present a Document View Controller, we should [inaudible] reference to a document.

Now to set document function in our case is asynchronous and that's because loading a document should be asynchronous because file [inaudible] is involved.

We're reading from the disk and you shouldn't do this on the main thread.

So let's take a look at how we should implement this.

First, we simply keep a reference to our document.

We then go ahead and load our view controller and then we call the open function on our document.

Now this will do all the work in the background and will give us a call back once it's back.

Now if anything went wrong during the loading of the document, we're going to get a call to handle error user interaction permitted on the UI document subclass.

Since we want to be good developers, we have to implement this function.

If we succeeded, we can go ahead and take the document and pass it to our particle View Controller and our editor View Controller.

Now the Document View Controller really is just a container view controller with a particle system on the left and the editor on the right.

Now in any case, we have to call the completion handler to indicate that we're done with setting the document.

Now that's about opening a document.

But of course we also want to dismiss our Document View Controller at some point.

Same thing.

Instead of calling the open function, this time we call obviously the close function.

This is asynchronous again because we are saving the document if required.

And the completion Handler, we just dismiss the Document View Controller.

Now the Document View Controller is pretty much done at this point.

So we can go ahead and take a look again at the Document Browser View Controller.

This is the one that is in charge of presenting our document view controllers, either when we create a new file or when we open an existing file.

Let's take a look at this again.

So when we create a new file, we get a call back to did Request Document Creation With Handler.

We obtained the URL from our NS main Bundle and passed it back via the import handler and a copy operation.

We'll either get a call back to did Import Document At URL or failed To Import Document at URL.

If we succeeded, we go ahead and present the document, which is just the same as when we open a file that already existed before.

Now when we want to present a document, we instantiate the Document View Controller from the storyboard and we pass the document via our function that we've just completed, set Document with a reference to a newly created document instance.

Once that is done, we just go ahead and present the Document View Controller.

Let's take a look at this in the simulator.

Switch back to the Browse view and hit the Create Document button.

A new file is created.

And there we go.

Our beautiful particles with an inspector on the right side.

We can change the values a bit, change the size, change the color.

And once we are done with it, we just close the document again by pressing the Done button.

Great. So creating documents and opening documents works like a charm.

But there is one thing that I don't really like yet, which is the Document Browser View Controller here has this white appearance whereas the particle View Controller has a really dark appearance.

So let's fix this.

As Pau mentioned earlier, there are three browser use interface styles that you can choose from.

First, dark, light, and white.

Now obviously, dark seems like a great choice for our situation here.

So let's switch back to the Document Browser View Controller subclass.

Now the view Did Load method of the subclass is a great moment to configure the document browser.

In this situation, what we can do is set the browser User Interface Style to dark and we can also modify the tint Color of the view of the Document Browser View Controller.

Now in this situation, using a bright orange probably will look great with our fire particles.

So let's take a look.

There we go.

This is the same Document Browser View Controller but in a dark appearance which should look much better than the one before once we open the Document View Controller.

Even the control URI now has the updated appearance.

Let's create a new folder, call it fire, and open a new document.

Now the transition between the two view controllers is much smoother and looks much better.

So that's pretty much all I have to tell you about the first demo.

And to get an overview of what we learned so far, I would like to hand it back to Pau [ Applause ]

So let's take a look at what we've seen in the demo.

First, we saw how to create a new document-based application from the Xcode template.

Then, we saw how to create new documents and how to open them.

And finally, we saw how to customize the appearance of the Browser VC to make it look like the rest of our app.

And now that we have the basics of this Browser VC, let's take a look at how to get and provide a great experience for our users.

In this section, I would like to talk about three different topics: open-in-place, how to provide custom actions in the Browser VC, and how to create a great opening experience.

So first, let's talk about open-in-place.

Open-in-place is a great feature that came with iOS 9.

It allows apps to share files between them without the need of copying them.

Also because of this, you have to be careful when accessing those documents because other apps might be already accessing them.

Now the Browser VC makes use of this feature in order to open the files from the Recents Popover, so if you're using the Browser VC in your app, you really need to make use of open-in-place.

If you're starting from the Xcode template, it's real easy.

You don't have to do anything.

If not, you will have to implement support open-in-place.

So let's take a look at the code.

First, we have to implement the application open input URL delegate method.

Here, first thing is to check if the input URL is a file URL.

And if so, we can call the Reveal Document method from the Browser VC.

This method will reveal the document in the Recents View and call us back when it's ready.

Now we can load and present the document as we did for open and creation.

If it fails, we need to handle the error and present some UI to the user.

Now let's take a look at how to add custom actions into this Browser VC.

There are three different ways of add custom actions.

The first one is the UI Document Browser Action.

You can add these actions when the user performs long press on a document and when the user enters selection mode.

In order to create them, you need to give an identifier localized Title and availability in the handler.

The availability has two values: menu and navigation bar.

Menu will make the action appear when the user performs a long press and the navigation bar will make the action appear when the user enters selection mode.

The handler will give you the array of URLs that the user wants to use for the action.

Now unlike the Open URL, this method you will only have access to these URLs until your application gets killed.

Now that we have our action, you need to set the supported content types.

The Browser VC will use the content types to know when to display your action.

Then, you need to set the supports multiple items to specify if you can support multiple items at once.

And you just need to set the custom actions that you created into the custom action array of the Browser VC.

The second type of actions are the UI Bar Button Items.

You can add these actions in the navigation bar of the Recents VC and the browse, sorry, the Recents View and the Browser View and you can add them in the trailing or leading sides of the navigation bar.

The third type of actions are the ones that you can add in the UI Activity View Controller.

The Browser VC will show this view controller when the user performs the share action.

The Browser VC will let you have control of this activity view controller before it gets presented.

And also, it will let you add custom actions when it's creating this UI Activity View Controller.

So let's take a look at the code.

If you want to add additional actions, you need to implement the document Brower application activities for document URL delegate method.

If you want to have access to this Activity View Controller, you need to implement the Document Browser will Present activity View Controller.

And that's all for the actions.

Now as you've seen already in Files, there's a great opening transition that goes from the thumbnail to the full screen.

And Files app is able to do this thanks to the new UI Document Browser Transition Controller.

This class will let you set display loading progress on top of the thumbnail while you are loading the document.

And it will also let you animate with Zoom transition when you're presenting the Document View Controller for the document.

So now, let's take a look at the workflow.

First, you will have to get the URL that the user just picked.

Here, you will start loading the content of the document.

And while loading it, you will have to update the Transition Controller.

Once the document is fully loaded, you just need to present the document and use the Transition Controller to drive the animation for the presentation.

So now, let's take a look at how it works.

First, once you have the URL that the user picked, you need to create the progress object that will track the loading of the document.

Here, you create also the transition Controller that will track the loading and that will drive the animation from the thumbnail to the full screen.

Now you just need to set the progress onto the transition Controller.

Here, we are ready to load the document.

In our example, the load Document method will load the document while updating the progress that we created before.

And when the document is fully loaded, it will call us back.

Here, we just need to present the Document View Controller.

Now, if we stop here, we will get the [inaudible] from UIKit which is a slide from the bottom but we want to have this nice zoom transition.

And for that, we need to implement the transitioning delegate of the presented View Controller.

The transitioning delegate needs to implement the UI View Controller Transitioning Delegate protocol.

In this protocol, you need to implement two main methods: the animation controller for presented view controller and the animation controller for the dismissed view controller.

Here, you just need to return the transition controller that we created before.

And now I will like to hand back to Raffael to show you how to implement all these advanced features.

Raffael [ Applause ]

.

Thanks, Pau.

So in this second demo, I'd like to show you three cool things.

First, we're going to take a look at open-in-place and how easy it is to adopt it with your Document Browser View Controller application.

Next, we're going to take a look at custom actions.

We're going to add a new action that shows up in the long press menu when you tap and hold a document.

And last but not least, we're going to implement a custom view controller transition to improve the user experience when we open an existing file or create a new one.

So let's just jump back right into our project.

Now let's talk about open-in-place.

Open-in-place is a great feature that has been introduced with iOS 9 and it allows you to work on the file that the user has chosen instead of on a copy of it.

Now adopting it is super easy.

And, in fact, if you come from the document based apps template, you have literally nothing to do.

The way it works is when the user taps the document outside of your app, iOS will make a call to your app delegate to open the URL with options.

So let's take a look.

Now in this function, what we do is first we make sure that the URL that we get from iOS actually is a file URL.

If it's not, we should probably return because we are not in the situation that we expect.

Once we pass that test, we get our document Browser View Controller which is the root View Controller of our application.

And we take the URL and pass it to the reveal Document function.

Now the Document Browser View Controller again will do all the heavy lifting for you in the background.

It will process the URL, move it if required, and once it's done, we're going to get a call back with our completion handler.

Now again, if we get an error, since we want to be good developers, we're going to handle the error appropriately for example by showing an alert view to the user.

If everything went right, we just go ahead and present the document with that new reveal Document URL.

That's literally all you have to do to support open-in-place in your document-based application.

Now let's take a look at custom actions.

So our particle systems are really beautiful, right, and we might want to share them with our friends.

So I'm going to add a new action that shows up when you long press a document to export this particle system as a GIF file or a GIF file.

Now let's take a look at the Document Browser View Controller again.

The view did load method is a great moment to configure these actions.

So, therefore, I'm instantiating a new UI Document Browser Action.

I give it an identifier that is unique throughout the app, a localized Title, and I set the availability to menu only.

So this will make sure that this action only shows up when you long press a document inside your Document Browser View Controller grid.

We also have to give it a handler which is the one that will be executed whenever the user taps our action.

In this situation, we just go ahead and log [inaudible]to the consol.

Next, we define the action supported Content Types to be com.example.particles with just the UTI type we defined earlier.

So just make sure that only our own files will get this action in the menu.

And last but not least, all we have to do is define the custom actions of our Document Browser View Controller to be array containing this newly created action.

Let's try it out in the simulator.

Now on our existing file, we perform a long press and we see that there's a new action showing up here, export as GIF.

Once tapped, we see that in the console the handler of the action has been executed.

That was pretty easy.

Now let's move to the third and the coolest things, the coolest thing that I wanted to show you, which is custom view controller transitions.

Right now when we present our Document View Controller, we get a simple slide up amination that is provided by UIKit and that's already pretty cool but it's not really the way it should look like.

Instead, the way it really should look like is the user taps the document thumbnail and the thumbnail grows into the particle system on the left side of our Document View Controller.

So let's take a look at how we can make this work.

Therefore, we switch back to the present document function that we created earlier.

Now the way custom View Controller transitions work is you register yourself as the transitioning delegate of the view controller that is about to be presented.

Before it is presented, UIKit will call us and ask for the transitioning controller.

We give back the transitioning controller and that object will be in charge of driving the animation from view controller A to view controller B.

View controller A in our situation is the Document Browser View Controller.

View controller B is the Document View Controller.

Now Pau mentioned that earlier the Document Browser View Controller already gives us this transitioning controller for us.

We just have to keep a reference and pass it back to the function that UIKit will call.

So first, we register ourselves as the transitioning delegate of the document View Controller that is about to be presented.

Next, we obtain a new transitioning Controller by calling the transition Controller for Document URL on our UI Document Browser View Controller.

Now this object doesn't really need a lot of configuration.

The only thing it really needs is the target View.

The target View is the one that we're going to animate to.

And in our situation, that's the particle system on the left.

We keep a reference to the transitioning controller that we've just obtained via our variable.

Now the last thing we really have to do is implementing the UI View Controller Transitioning Delegate protocol.

Now, therefore, we implement the two functions: animation Controller for Presented View Controller and also, because we want to support closing documents, animation Controller for dismissed view controller.

In both functions, all we have to do is return the transitioning controller that we've just obtained.

Let's try it out in the simulator.

Beautiful, isn't it?

We get a nice transition from the thumbnail to our particle system.

And when we're done with the file modifications, we tap the Done button to close the file again and we transition beautifully back to our UI Document Browser View Controller.

So that's pretty much it for the second demo.

Let's take a look at what we've learned so far.

First, we've taken a look at how easy it is to support open-in-place in your application.

The UI Document Browser View Controller really does all the heavy lifting for you.

Next, we've implemented a custom action that shows up only when you long press a document in the Document Browser View Controller.

And last but not least, we've improved the user experience a lot when opening and closing documents by implementing a custom view controller transition using the UI Document Browser Transition Controller.

Now that's pretty much it for the second demo.

And to tell us what's new on the Quick Look side, I would like to hand it over to my colleague and friend Maxime.

Maxime [ Applause ]

.

Thank you, Raffael.

Good afternoon, everyone.

I'm sure you have all seen the great thumbnails of the files app and I'm sure you wish your own thumbnails could show up in any document browser based app.

You are now going to see how this is possible thanks to the new thumbnail extension.

Currently, [inaudible] particles app that we're building throughout this session, all we can are generic icons.

We could highly improve the user experience by displaying instead representative thumbnails that indicate to the user the content of the files.

So how can you provide thumbnails of files that have been downloaded and are available on the device?

This was already possible before iOS 11 through UI Document.

What you have to do is create a subclass of UI Document and return the thumbnail from your subclass.

This only works for files created by your application and this has good performance because when iOS will ask your subclass of the thumbnails, the file will be already loaded.

Let's take a quick look at the code.

What we have to do is implement the file Attributes To Write to URL for save Operation method in your UI document subclass and return a dictionary of thumbnails from this function.

So this is nice but this again works only for files created by your application.

So how can you provide thumbnails for files created by [inaudible] applications and by other applications?

For this we are providing you with a new thumbnail extension which is system wide.

It means that this extension, means that any thumbnails generated by [inaudible] extension will be displayed in any document files based app that displays files that your extension can provide thumbnails for.

This extension works with all cloud vendors and is part of the Quick Look framework.

Let's see how this works.

First, your document browser-based app is displaying Let's say that the document browser based app is displaying a set of files.

And if we want to display thumbnails for these files to have a good user experience, it's going to Quick Look for thumbnails.

Quick Look, we notice that for some of these files, [inaudible] extension is the one that can provide thumbnails, so it's going to forward the request to your extension.

Your extension will generate thumbnails, return them back to Quick Look which will finally forward them back to the app that asked for the thumbnails, which will be able to display them.

Let's see how you can get started.

This is actually pretty simple because we added a new template in Xcode that contains some sample code for you as well as an Info.plist.

After creating your extension, you will want to head to the Info.plist file and edit it.

So first thing you will have to do is add all the UTIs you can [inaudible] to QL Supported Content Types array.

Please note that you can only provide thumbnails for UTIs you own and export and that iOS will check for UTI equality and not UTI conformance.

So we'll have to make sure to list all the UTIs inside [inaudible] of the plist.

Now how can you actually provide thumbnails for files?

There are two ways.

You can either draw the thumbnail or return the image file URL.

So the most preferred one is of course the first one, drawing the thumbnail, because it's the most flexible one.

Let's see how it works.

So any method you will have to implement in this extension will receive a parameter of class QL File Thumbnail Request which contains three [inaudible].

The file URL, the URL of the file we want to send a file, the maximum size of the thumbnail which is requested, as well as the scale.

What do we have to return is a QL Thumbnail Reply object containing the Drawing Block and context Size.

Let's see why you need to return the context Size.

The maximum size parameter of the request indicates to you the maximum size of the CG Context you can draw your thumbnail into.

Now let's say that we want to draw this image into our context.

As you can see at full scale, it's bigger than the maximum size of the Context.

So what we'll have to do is downscale it to make sure that it can fit within the CG Context.

But if we load this image into the context we have on the left, we'll end up returning a thumbnail with unused [inaudible], meaning a floating thumbnail, which is not what we want.

So we'll have to determine the correct context size in which we want to draw and pass it to the QL Thumbnail Reply.

Thanks to that, our Drawing Block will receive CG Context correctly set with the requested size, the context Size, and we'll be able to draw the thumbnail [inaudible].

Now if you don't want to draw a thumbnail and you prefer returning an image file URL instead, this is quite simple.

You will receive the same QL File Thumbnail Request and all you have to return is a QL Thumbnail Reply containing an image file URL.

In this case, Quick Look will be the one that will take care of downscaling or upscaling of thumbnail.

It will keep the aspect ratio of your file so that the thumbnail will [inaudible].

Let's now take a look at how this works in code.

The only method you have to implement is called provide Thumbnail for request handler.

The first thing we do in this example is extracting all the parameters of the QL File Thumbnail Request.

This means the file URL, the maximum size, and the scale.

Out of these parameters, we determine the context Size in which we want to do our thumbnail, just like in the example we saw before.

After that, as we said, we need to provide a drawing Block.

So here we create it and this is [inaudible] that we'll have to draw a thumbnail.

So drawing Block has to return a success value to indicate Quick Look [inaudible] it was actually able to provide a thumbnail.

Finally, we create the QL Thumbnail Reply out of the context Size and the drawing Block and we call the completion handler with our reply as well as [inaudible].

Here we [inaudible] nil because we always want to provide a thumbnail but if for some reason you don't want to always return a thumbnail for all the requests, you will have to provide an [inaudible] to indicate quickly that you don't want to provide a thumbnail for this request.

If you'd like to return an image file URL instead of drawing a thumbnail file request, you implement the same method but you call the completion handler with a QL Thumbnail Reply containing the image file URL.

In this simple example, we just return an image from our main vendor.

After creating your extension, you will of course want to see your beautiful new thumbnails.

You can see them in any document browser based app that displays your files.

So here, what we can see on the screenshot are thumbnails that come from the extension of Particles app but we are inside the Recents [inaudible] Files app but still we see them.

You now know how to build great document-based applications thanks to the UI Document Browser View Controller and the thumbnail extension.

So how can you improve the user experience even further?

[Inaudible] UTIs, you will likely want to be able to provide previews that iOS can display in any application.

We are now going to see how this is possible thanks to the new Quick Look Preview extension.

By default, Quick Look [inaudible] set of file types.

This means that Quick Look by default cannot preview your custom file types.

But I have good news because starting with iOS 11, you will be able to provide previews to Quick Look and extend the capabilities of Quick Look because we are opening Quick Look to [inaudible].

We are opening QuickLook [inaudible] so when you preview extension which is system-wide, this means that again any application that uses Quick Look will be able to display your previews and you can also decide to provide previews for Spotlight items [inaudible] by your application.

These previews will be visible when peeking on Spotlight [inaudible].

On the iPhone, that's [inaudible].

Your previews will be [inaudible] in Quick Look.

They will benefit from the full Quick Look experience and the previewed as part of QL Preview Controller just like any other [inaudible] preview.

Quick Look will take care of displaying a loading spinner while waiting for your extension to return the preview.

Let's see the flow.

First, Quick Look notices that it can't preview file by itself but will ask for extension for preview.

Your extension will take some time to generate a preview.

Meanwhile, Quick Look displays a loading spinner.

You don't have to take care of this.

And when your extension is ready to display the preview, you will have to call the completion handler in your code to notify Quick Look that it can actually display your preview.

Just like [inaudible] extension, you can get started pretty easily because, again, we have a new template ready for you that contains some sample code, a storybook, and an Info.plist.

After creating your extension, again you will want to head to this Info.plist and edit it, add edit it, add all the UTIs [inaudible], sorry, all the UTIs [inaudible] to the QL Supported Content Types array.

Just like for the thumbnail extension that you can only provide previews for images you own and export and that again, iOS will check for UTI equality and not UTI conformance.

If you wish to provide previews for Spotlight items indicated by your application, you will have to set the QL Supports Searchable Items key to yes.

Now let's take a quick look at how we can [inaudible].

If you want to provide previews for file, you will have to implement the prepare Preview of File at URL completion handle [inaudible].

And all you have to do here is load the file and call the completion handler so that Quick Look displays your preview.

You can call the completion handler asynchronously which is the case in this example.

If you wish to provide Spotlight previews, you will have to implement the prepare Preview of Searchable Items identifier query String, completion Handler method.

The query String parameter can be used to highlight any part of the preview for the user.

This is the query String that the user [inaudible] in Spotlight before interacting [inaudible] that you index with your application.

Just like with file example, all you have to do is prepare your controller and call the completion handler.

You can test your preview in any application that uses Quick Look, for example mail or messages or in Spotlight if [inaudible] which is the case in this example.

We are here peeking on the result index by the particles app.

I'd like to finish this extension tour with a few performance recommendations.

When dealing with extension, you always have to make sure to be fast and in this case it's very important.

You will have to load the thumbnail quickly especially think of a case for instance of the user calling in the document browser you want your thumbnails to be there as fast as possible for a good user experience.

For the Quick Look previews, you will also have to make sure to load your previews fast because Quick Look is expected to be quick.

Also not that you shouldn't have any background job after calling the completion handler.

Keep in mind that with extension memory is very limited, so avoid linking against two large libraries and check for leaks.

Let's now recap quickly everything we talked about today.

First, we talked about some document browser APIs.

We mainly talked about UI Document Browser View Controller and how you can make use of it to create a great document-based application.

You learned about its basic and advanced features.

We then saw how you could make your custom file tags [inaudible] on iOS 11 thanks to the new thumbnail and Quick Look preview extensions.

Now let's take another look at the requests we have received from you in the past two years and see how we addressed them, so everything we talked about today.

UI Document Browser View Controller provides you with a unified UI for file browsing.

The new local storage and other cloud providers give you access to files from other applications in [inaudible].

The new file provider extension allows you to have seamless access to other Cloud Providers.

And iOS now has a deep integration of custom file types.

As usual, if you wish to have more information about our session, you can visit Apple's website.

We invite you to check out these related sessions, the Drag and Drop session that was earlier this week and the upcoming What's new in Core Spotlight for iOS and macOS and File Provider Enhancement sessions.

You can also check out previews Building Document-Based Apps from 2017.

Thank you all for your attention.

[Inaudible].

Bye.

[ Applause ]

Apple, Inc. AAPL
1 Infinite Loop Cupertino CA 95014 US