App Frameworks • iOS, OS X • 51:25
Quick Look is a technology that displays previews (OSX and iOS) and thumbnails (OSX only) of your documents. It helps the user quickly identify the files he is interacting with.Learn how to take advantage of Quick Look to display document previews on the Mac, iPhone and iPad. Learn how you can generate thumbnails and how to write plug-ins to support your own document formats on the Mac.
Speakers: Philippe Champeaux, Julien Robert
Unlisted on Apple Developer site
Downloads from Apple
Transcript
This transcript was generated using Whisper, it has known transcription errors. We are working on an improved version.
Hi, welcome to session 106 System-wide Previews with Quick Look. My name is Philippe Champeaux and I have been working on the iOS part of Quick Look for the last three years. I will be joined on stage by Julien Robert, who is one of the two original inventors of the Quick Look framework. We are very excited to be here in San Francisco today. And I hope that our terrible French accent won't be too much of a problem for you today.
So what are we going to cover today? Well, first, I will talk a bit about what Quick Look is, how it works, and what you can use it for. Then we will show you how you can use Quick Look to display previews inside your iOS and Mac OS X application. After that, I will show you how you can ask Quick Look for thumbnails for all your documents and files. And finally, Julien will show you how you can be part of the Quick Look process by providing a generator for your own document types.
So, what is Quick Look? Well, the goal of the Quick Look framework is to display thumbnails on previews of documents. By default, we support all the basic document types: images, PDF, various text files, QuickTime movies, audio files. We also support out-of-the-box iWork and Office documents. In Mac OS X, Quick Look can also display your documents if you provide a generator for them. Let me give you a few examples of places where you can see Quick Look in action.
First, you can see it in your mail. When you receive an email with some attachments, you can preview the attachment right inside the mail application. This is true both in Mac OS X and in iOS. Another very good example is the Finder. In this image, you can see icons in the bottom window. You can see flat thumbnails in the Cover Flow view on the right window. And you can see, of course, the preview panel that you get when you press the spacebar.
In iOS, we have integrated Quick Look inside the Safari application. So if you are on the Internet browsing to a Word document or a Pages document, you don't have to save it. You can preview it. You can view it directly inside Safari. In Mac OS X Lion, we have also integrated Quick Look inside the dock on the Spotlight menu. So when you search for something, if you have several matches, you can preview the matches before opening them. It's very convenient.
Quick Look is a public framework available in your applications. This is a small Cookbook application that we are going to use as an example during this presentation to show you how you can integrate Quick Look inside your own applications. So how does it work? Well, Quick Look is divided into two functional parts. First, we have the producer, which reads the file. And then we have the consumer, which displays the content inside your application.
The goal of the producer is to translate complex document types into something that Quick Look can understand. So it can be HTML, PDF, text, images and movies. It uses a plug-in architecture, so when the user wants to preview a document, Quick Look will look for the associated plug-in and load it on demand. In Mac OS X, we provide an Xcode template so that you can write a generator for your own document types.
The goal of the consumer is to display the content inside your application. There are two kinds of content. First, we have rich content, which we call previews, which are displayed in the preview panel and the preview view in Mac OS X and in the preview controller in iOS. In Mac OS X, we also have a second type of content, which are thumbnails. Thumbnails are just static images which represent the content of the document.
To summarize, in Mac OS X we support previews, thumbnails and we have this public plugin architecture. In iOS, for now, we only support previews. We don't really need thumbnails anyway since there is very little file manipulation in iOS. So, now that you know what Quick Look is, we will show you how you can be a consumer for Quick Look. How you can use Quick Look to display previews inside your application.
And for that, Julien will come on stage and show you how you can use Quick Look in Mac OS X. And I will come back after that to show you how it works in iOS. If you are only interested in iOS, you should still pay attention to what Julien is going to say because a lot of stuff is common and I won't repeat it. So please welcome Julien.
Thank you Philippe. So we'll see how to display previews on Mac OS X and more specifically on Lion. So on Lion you have two choices to display previews to the user. First one is to display using a panel that we call a preview panel. This is a regular subclass of an NS panel. And there is one shared panel per application. So the policy of the panel is to always show the current selection in the key window. So if this is changing, the preview panel needs to be updated accordingly.
But you may also want to use a view that we call the Preview View. And it's a regular subclass of NFVue, so obviously you can have many of these views in your application. And as opposed to the Preview panel, you are directly in control of what's previewed in the view.
But let's first talk about the Preview Panel. In Lion, as you may have seen in developer previews, we have a new user interface for the Preview Panel. And I'd like to point a few new features of this new interface. So first, when your application is displaying the Preview Panel in your application, and when your application goes in the background, the Preview Panel will stay visible and will not hide anymore.
We also added some swipe gestures so that the user can easily navigate through a multi-selection in the preview panel. And this works both in the panel and in full screen. And as you can see on the top right of the preview panel, there is a new open button that makes it very easy for the user to open the document inside the application.
And finally, the previews are not done in a remote process, meaning that if something goes wrong with the preview, your application will be unaffected. So this is good for security and for stability reasons. So let's get technical now. So to use a preview panel, the first thing you want to do is link against Quartz and import the Quartz framework. And you use a shared preview panel to get this shared instance.
Then you want to display the panel. Since it is a regular subclass of NSPanel, you just use NSWindow APIs to order it in and out. And there are also some methods to make it full screen. The last two methods work whether the preview panel is already visible or even if it's not. And if it's not, it will go directly into a full screen slideshow.
So as I said, the preview panel is always displaying the current selection in the Key Window. So for example, if the Key Window is changing, like that, you can see that the panel is updated to reflect the new selection in the Key Window. So how does this work? Quick Look is listening for changes in the responder chain. If something is actually changing, it will try to find a controller for the panel. To do that, it will walk in the responder chain and send this method to each object. The first one that will reply with "yes" will be elected as the controller for the panel.
So this controller is sent this method to notify it that it will really begin to be controlling the panel. And that's where setup should happen on the preview panel. And when the ownership of the preview panel is given to another object, the previews controller is notified using this method. So the important thing is to not assume that you can do whatever you want with the preview panel at any time. And you are the owner only after receiving the BEGIN method and before the END method.
So, now that you are the controller of the preview panel, you want to display content in it, obviously. So we have very simple data source methods. So you first return the number of items you want to display in the panel. And then you will be called for each index to return the item.
As you can see, this is what we call a preview item. If this is your existing data model and you have custom objects in your application to represent files, you can directly give them to Quick Look and to the preview panel, providing that they implement the actual preview item protocol.
So what is this protocol? It's very simple. Basically, you just have to return the URL that points to the file you want to preview. And you may also be interested to return a custom title to display in the preview panel. As a side note, NSURL already implements this protocol, so you can directly give URLs to the preview panel if that fits your needs. To open and close the panel, we have standard shortcuts. They are Command Y and Spacebar. You can use either of those or both.
Another interesting thing is that when the preview panel is open in your application, it's frontmost. But you may want the user to still be able to interact with the view that is below. So in that case, you would implement this delegate method. And if your view handles the event in place of the preview panel, you return yes. So that the panel does not undo the event again. So the typical use case is, for example, if you have a table view and you want the user to be able to change the selection with the arrow keys. So you would use this technique.
[Transcript missing]
So to do that, we have delegate methods that you should implement. The first one will provide a nice zoom effect from the item to the preview panel. And the second one, if you return an image, this will make a crossfade from this image to the preview panel to really make a beautiful transition.
So there is a content track. So what is this content track? If this is the transition image you return in this method, the content tracks correspond to this area in the image. So this is really the content of the preview that we will match to the content of the preview panel.
So that's all for the preview panel and let's talk about the preview view now. So as I say, the preview view is just an S-view, so you can unlock it like any other view. But in Lion, we've added an optional style parameter that lets you customize the look of the preview view. So we currently have two styles. The first style is the default style and we display previews with regular controls. As you may have seen in Snow Leopard. So in the example, you can see there is a time slider at the bottom of the preview.
This is more suited for full previews with pretty large size. But you may be interested with the new style that we introduced in Lion, which is what we call a compact style. It's more suited for smaller previews and things like inspectors, but you may just prefer the look, so you can use that anyway. So in the example, you can see that the movie has rollover controls.
To provide content in the preview view, it's much simpler than the preview panel because there is a property that you directly set. Once you've done that, the preview view will load the preview in the background asynchronously. But the thing you don't want to do is to assume that as soon as you set this property, the preview is ready. Because it may take time to generate the preview. And if the file that you are previewing is modified while the preview view is showing its preview, you can ask the preview view to reload by calling this method.
One important aspect of the preview is to correctly manage its lifecycle. So by default, the preview view will be discarded when the window containing it is closed or when it's removed from the view hierarchy. So this is good for very simple cases. But if your application manipulates view in a bit more complicated way, or if you want to reopen the window containing the preview, you should use manual mode instead.
And there, if you do that, you are responsible to discard the preview at the correct moment by sending the close method. So don't forget to do that because if you don't, some resources will not be allocated, so you will see memory growth in your application, which is bad.
And in Lion, we've introduced a new feature that we call seamless opening. So you may also have seen that in the developer previews, but just to show you. So this is an icon in Finder, and when the user double clicks on it, You see that it zooms from the icon to the document in preview, like it zooms from the icon to the preview panel. So it's exactly the same animation.
So seamless opening is to get a smooth transition from the icon or a preview to the full document in the application. And it integrates very well with Quick Look and especially the new open button that there is now in the preview panel. And the good thing about this feature is that you can get it for free because there is no API. But there are a few conditions that your application has to meet. First, your application needs to have a correct usage of NS Document APIs. So there is an AppKit Lab this afternoon if you want to check with them if you are doing the correct things.
The second condition is that your application needs to launch and open the document quickly enough. So quickly enough being less than a second. So I'd like to make a little demo and show you how easy it is to adopt Quick Look in a sample application. So this is our sample cookbook application that I will briefly show you first.
This is a list of recipes and then when we click on this button, we would like to show the preview panel with images and other stuff that correspond to the recipe. The second thing we want to do is when we actually start making the recipe, we would like to have an illustration in this area to make the step more obvious. To do that, we will use the preview view. So let's first add support for the preview panel.
So when we click on the top right image in the application, this method is called. So the first thing we want to do is to order in the preview panel. So we get the shared instance and order it in if it's not visible or out if it is already.
And the preview panel works with a controller. So the next thing we will do is to add Method to set ourselves as a controller for the preview panel. So we accept to be the controller and when we actually begin to be it, we set ourselves as data source and delegate. So we need to implement the data source and delegate protocol. So let's just declare that we do.
And then we will implement the data source methods. So we have here an array and we just return the number of items in this array and return the object as the index in the array. Pretty simple. And the last thing we want to do Because Quick Look accepts objects that implement the actual preview item protocol, we will implement this protocol in our objects. In this case, the objects are steps.
[Transcript missing]
For the URL, we just return the location of the file on the disk. For the title, we return the name of the recipe instead of the name of an image. The interesting thing is that this object is shared with the iOS demo application that Philippe will show you later.
So since we already implemented this protocol, he won't have to do that. So let's run now and see how it goes. So when I click here, I get my medias and I can swipe between them. So this is a new Lion feature. So it's working okay. It's just missing the zoom as you may have seen.
So we will implement that. And to do that, we will add the delegate methods like that. So we get the frame of our image button. Then it's just some calls to adjust with the ratio of the image. And we convert this frame to screen coordinates and return that. But we want also to use a transition image. So we just return the image in the button to have a fade from this image to the panel. And now if we try again.
So we have a much nicer transition that really highlights that the preview is from this item. So we are done with the preview panel implementation and now we will do the preview view implementation. So the first thing we want to do with the preview is to create it, of course.
For the demo, we will use the new style in Lion, that is Compact Style, so we will have rollover controls. So once it's created and added to the view hierarchy, we want to set the content of the preview view. So to do that, we will use bindings and bind the preview item property of the preview view to the selected step in our table view. And we don't forget to unbind it. So that should be enough to have our steps. Let's see.
So it's working correctly, but there are still a few things that we could improve. Well first, the movies do not play automatically. So since the controls are on rollover, we can't see easily that it's a movie. So we want them to start automatically. And the second thing, so if we change to another recipe and back, it's crashing because as you can see, it says that we try to set a preview item on the preview that's already closed. So this is the typical thing that happens when you are using the automatic mode of the preview lifecycle.
So this is a good example of using manual mode because when we switch to another recipe, the view is removed from the view hierarchy and it's added again later so it's not working because it's killed automatically. So let's use that. And don't forget to close the preview when we are done. So in this case, that's when the application terminates. Let's also autoplay the movies and run again.
So start cooking and now you can see that the movies play automatically. And that if I switch to another recipe and back, it's still working. So this concludes our implementation of Quick Look in Mac OS X. And I will just sum it up what you need to do to implement Preview Panel Support. So first you need to import a link against the Quartz framework.
You need to add calls to open and close the preview panel. Then you need to implement the controller methods to get your object to be the controller of the preview panel. And of course implement the data source methods. Once you've done that, you will want to make sure that the selection, when the selection is changing, you correctly update the Preview Panel by sending reload data.
Finally, you want to have the zoom animation, so you will implement the two delegate methods that we just showed. And that's all what you need. And to talk about previewing in iOS, I will call back Philippe on stage. So, now that you have seen how it works in Mac OS X, let's compare this to iOS. Well, like I said, in iOS, it works exactly the same as in Mac OS X for the most part. And in particular, the model and the data source are the same. What changes is the way you present the preview.
Fortunately, it is a bit easier. It is easier for two reasons. First, in iOS, every application is full screen. So you only see one application at a time. This means that we don't need on iOS the Shared Preview Panel that we have in Mac OS X. The second reason is that we have those very nice UI View Controllers in iOS.
So they are very easy to use and very powerful. So we chose to make the Preview Panel a subclass of UI View Controller. We named it QL Preview Controller. So this means that since it is a standard UI view controller, you will use the methods that you already know to present them on screen. It's a very standard API. And in the end, it will integrate perfectly in all the iOS workflows.
The Preview Controller supports all the same basic document types as in Mac OS X. It also has an open button like in Lion. As a bonus, we also support printing. If you want to add support for printing inside your iOS application, all you have to do is present a Preview Controller and Quick Look will take care of the rest.
In iOS 5, we are introducing a new way to navigate between multiple documents. Now when you are full-screen on the iPad, you can swipe between items exactly like in the photo application. It says that we can swipe between all documents supported by Quick Look. So, for example, from a spreadsheet to an image, to a PDF, to a movie, to whatever you want.
We are also introducing a new way to navigate inside long documents. If you have, for example, a 50-pages document, when you show the navigation bar, you now get the thumbnail scrubber on the right side of the screen, which lets you directly select the page that you want to go to. So if you want to go to the bottom of the document, you don't have to scroll, unscroll, unscroll endlessly. You can tap directly to the page which interests you.
So how do you use the Preview Controller? Well, like I said, it's very close to the desktop. There are just a few changes that I am going to highlight. First, you don't click against quarts. You link directly against the Quick Look framework. Since we don't have a shared preview panel in iOS, you have to create your own preview controller. Create it with QLPreviewController.alloc.init. Set yourself as data source. Optionally, you can set yourself as delegate if you want to customize the zoom animation.
To present it, since it is a subclass of UI View Controller, you use the methods that you already know with UI View Controllers. Either present model View Controller animated or push View Controller animated. The one you will use depends on your context. If you have a navigation controller already, you should probably push the preview controller inside the navigation controller. If you don't, you can present modally and then the view will slide up in the iPhone and be presented full screen on the iPad.
When your Preview Controller is on screen, you then have to provide content. And we use the exact same data source model as in Mac OS X. The only difference is that since we have a Preview Controller instead of a Preview Panel, we had to rename a bit those methods. We have a number of preview items in Preview Controller and Preview Controller preview item at index.
This returns the same preview item object that is in Mac OS X. We have the same Zoom Animation Delegate method as on Mac OS X, which are PreviewController.frameForPreviewItem in Source View and PreviewController.TransitionImage for PreviewItem content-right. If you have paid attention to what Julien said a bit earlier, you may notice that there is a new Source View parameter in the first method. This is because in iOS, everything can be rotated, so we really need a reference view to make sure that we are in the good coordinate.
So let me show you how it works in iOS. I'm going to use an iOS, iPhone and iPad version of the Quick Look application that Julie used. On the desktop. So it is a very standard iOS Application. On the iPhone, it uses a navigation controller To show first the list of recipes and then when we click on a recipe, the list of the steps. What we want is to show the detail of the step when you click on one of the steps. So let's do this. So first we have to create our own Preview Controller. So we import Quick Look. We declare our controller.
And then we're going to add an accessor to create the controller on demand. Now we want to show the Preview Controller when the user taps on one of the rows of the list of steps. So we're going to implement the TableViewDelegate method TableViewDidSelectRowAtIndexPath. We retrieve the Preview Controller and we push it inside the Navigation Controller. As you can see, Xcode is not happy because we haven't implemented the QLPreviewController data source protocol.
Since Julien already implemented the QLPrivateItem protocol in the Steps objects, I don't have to implement them again. So we return, we use ordered steps which contains the list of our steps. We return the number of steps on the step at index here. So this should be enough to show If I tap on the first step, I get the list of ingredients. But it's still not working perfectly. As you can see, if I tap on one other step, I always see the first step.
This is because before pushing the button, To set the Preview Controller in the Navigation Controller, I should make sure that we are showing the correct step. I'm going to use CurrentPreviewItemIndex to set it to the row of the index path. And now, when I tap on any of the steps, I can see and the other speakers.
Now let's have a look at the iPad. On the iPad, we are using a USB View controller to show the list of recipes on the left and then the steps on the right. What we want is to zoom the small image, the plate image to full screen to show the steps full screen.
In this case, we don't want to push inside the navigation controller. We want to present manually. I'm going to delete this method and replace it with a check. If we have a navigation controller, we're going to push inside the navigation controller. This is the iPhone case. But if we don't have a navigation controller, this means that we're on the iPad and we're going to present modality. So let's try again. Now if I tap on one of the attachments, I get the full screen preview. I can swipe between my items, can view the videos, swipe to another one. But I still miss the zoom effect, so I need to implement the delegate method.
First, I set myself as delegate. And then I implement the two delegate methods. What we want is to zoom from the image from the UI Table View cell to the full screen. So I'm going first to retrieve the index of the item from the steps. Then I retrieve the UI Table View cell from the Table View.
When I have the cell, I can get the image view. Then I can use this image view as source view and return the bounds of this image view. Then for the zoom, I can return the image directly inside the image view to have this nice transition. Let's see how it works. If I tap on one of the attachments, I get the nice zoom effect.
There are a few things that you should and shouldn't do when you use a preview controller. First, and this one might sound obvious, make sure that your delegate exists until the end. In particular, on the iPad, we have two delegate methods which are called at the end of the zoom animation. First, we have preview controller will dismiss, and at the very end, we have preview controller did dismiss. So if you set yourself a delegate, make sure that your delegate exists until at least did dismiss is called.
Then do not set yourself as a preview item. The reason for that is that Quick Look will retain the preview item. So if you are a preview item yourself, we will retain you, you will retain us, and you will enter a return cycle. So in the end, you will leak both your ViewController and the PreviewController. Finally, do not try to customize the navigation bar. In iOS, the top UI view controller owns the navigation bar. So if you put something when you push the preview controller, don't be surprised if we just remove it and replace it by our own action button.
So this concludes the previewing part of this presentation. And now I'm going to talk about sunnellings. And like I said at the beginning, thumbnails only exist in Mac OS X. What are thumbnails? A thumbnail is a static image which represents the content of a document. We have two kinds of thumbnails.
First, we have what we call flat thumbnails. On a flat thumbnail, just give a quick overview of the content. Then we have icons. An icon is a flat thumbnail with added decorations which emphasize the file aspect of the document. So you can see here the page curl on the PDF or the reflection on the letterbox on the movie icon.
Flats and nails can be very high resolution, so they are perfect for inspectors or for preview pen. And they are also very useful if you want to integrate them inside some more fancy views like we did with the Coverflow view. Icons, on the other hand, are better fitted for collection of items.
So if you want to show a browser view or list view, you should use icons. Since they are much more physical than thumbnails, they make perfect file handles. If you want to show the user that he can click on an item or drag and drop the icon, you should use file handles.
So what are the APIs to retrieve thumbnails? We have two APIs. First, we have a very basic synchronous API. You just call ql_thumbnail_image_create, you pass the URL of your file, you pass the maximum size that you need, and you pass some options. This returns the thumbnail as a CG image ref.
As an option, you can set icon mode to True and this will tell Quick Look to add all the icon decorations. Be careful that this is a synchronous API, so it may take time to return. We try to be as fast as possible, but of course some documents are more complex than others, and we don't control all the generators. So don't call this in the main thread.
To simplify things, we have added an asynchronous API which uses GCD. You first have to create a QLSumbnailRef object with QLSumbnailCreate. You pass the same arguments as the previous function, so the URL, the maximum size and the options. And then you dispatch the request with QLThumbnailDispatcherSync. When the completion block is called, you can call QLThumbnailCopyImage and this will return the thumbnail. You could also call copyImage directly without calling dispatch async, but then of course the function will block until the thumbnail is generated. One thing that you shouldn't do is call dispatch async and then call copyImage before the completion block is called. That just wouldn't work.
You can cancel the generation of the thumbnail with QSumnailCancel. This API also provides a nice utility method which returns the content trait. Like Julien explained, the content trait is the exact frame of the content inside the icon. You don't usually need this information, but you can pass it to Quick Look with the zoom delegate method. Then Quick Look will be able to zoom perfectly from the icon to the preview panel or from the icon to full screen.
And now we are done with the consumer part of Quick Look. And Julien will come back on stage and show you how you can be part of the Quick Look process and write a generator for your own documents. So let's now see how you can extend Quick Look to support your document types. First, let's see an overview of how Quick Look plug-ins are working.
Quick Look plugins are living in the process that is called sandboxed. This means that some operations are not permitted, like network access or file access to something that is not the file you are previewing or sumnaling. If something bad happens, there will be a log in the console, so check for logs. But you shouldn't have to do what's forbidden.
So when Quick Look receives a request from the client to generate a thumbnail or a preview, it sends this request to the daemon, which chooses the correct plug-in to reply to this request. The plugin generates the thumbnail or the preview and sends it back to Quick Look, which then fulfills the request to the client application.
So let's see how you implement your Quick Look plugin. Once you've created your new project from the Xcode template, you will see two function prototypes that you have to implement. One for thumbnails and one for previews. So first let's focus on thumbnails. So you have a couple of few arguments, but the main ones are the thumbnail request and the URL pointing to the file that you want to generate a preview for. So you have two ways to reply to this request.
The first way is if you already have the thumbnail ready in form of an image of a data or URL, you give it back directly using one of the set functions and then Quick Look will send it back to the client. But the other option is if you want to draw the thumbnail live inside your plug-in. So in this case, you create a CG context. You draw in this context like any regular CG context and then when you are done, you flash the context to tell Quick Look that the thumbnail is ready to send back.
For previews, it is very similar. So the prototype is the same. And similarly, you have two ways to reply to a preview request. If you already have the preview in form of data or URL, you can directly use the set data or set URL representation and give back your preview to Quick Look specifying the content type of the data or URL you are giving.
And the other solution is to draw the preview live using the Create Context method and Flash Context method. Except that for previews, you have another option, which is to create a PDF context. So this will allow you to create a preview with multiple pages using Core Graphics, Begin Page and End Page functions.
So you flash your preview and then you are done. So now that you've written the code, you want your code to be actually cold. But first, I'd like to have a brief overview of what we call document types and also UTIs. For UTIs, our unique strings that should be unique across the system and are prefixed by vendor. They are defined in the info.playlist of applications or plug-ins. and they are registered and managed by Launch Services. So in our sample Quick Cookbook application, this is an extract of the Info.plist and this is where we define our UTI for Recipe documents. So we use com.apple.recipe.
The next thing you want to do is to get launch services know your plug-in. So you have to put it in known locations. So if your plug-in is generating thumbnails and previews for documents that are for your own application, you should ship it directly into the app bundle in contents library Quick Look. But if you want to ship a standalone plug-in, you can put it in /libraryquicklook or /tilda/libraryquicklook and it will be seen by launch services and registered.
In your plugin, you specify the UTI you are generating previews on Sunday for. In our example, you can see that we see com.apple.recipe in our Info.plist of the generator. The generator contains some attributes in the Info.plist and I'd like to show you a couple of them. First, we have what we call sizing attributes.
For thumbnails, you can specify the minimum size from which the thumbnail is meaningful. Meaning that if the client requests a thumbnail smaller than this size, we won't even code your code and we will just say that there is no thumbnail. And for previews, you can specify a default size that will be used for the preview panel when it's opening.
But we have also what we call running attributes. So if your code supports concurrent requests, you should specify it and it's a good thing to support concurrent requests. It's better for performance. But on the opposite, if your code needs to be run on the main thread, which is a bad thing but sometimes you don't really have a choice, you need to specify it to avoid some problems. And those are valid for both thumbnail and preview generations.
So I'd like to quickly talk about what are options and properties. Options are given from us to you and are meant to alter the generation of previews and thumbnails. So as an example, we have the scale factor option for thumbnails. On the opposite, properties are given by your plugin back to Quick Look to specify and to give us hints about how to display the thumbnails or previews.
As examples, for thumbnails, you can specify a custom extension to badge on the icon or even a badge image. For previews, you can specify a size that will be used by the preview panel. And of course, this size takes priority over the static size that you may have defined in the InfoDate playlist.
Optionally, you can also specify a custom display name for your preview that will be shown in the title of the Preview Panel. I will give you a quick demo on how to write a Quick Look plugin. I created a new project from the Xcode template. I've added a custom utility class to parse our recipe documents. We will first generate the thumbnail.
So this is pretty simple. Using our utility methods, we get the image inside the document and then we give it directly to Quick Look as a CG image. So now we want to test that. And to do that, we edit the scheme in Xcode and we add TrailManage. TrailManage is a tool that is used to help debug Quick Look.
So we add QL Manage and we set a couple of, a few arguments. So that tells it to generate a thumbnail. And here you can see that we are specifically giving it the path to our generator because it's not yet registered to launch services. So we had to specify it manually. And then this is the path to our document. So let's run it. And we have a nice thumbnail of our recipe. So we are happy with that and we will now implement the preview request.
Similarly, I'm using our utility methods to get the name, the content and the image of the preview. And then we are drawing using AppKit APIs. So we have a gradient and other things. And when we are done, we flush the CG content. To test that, we will edit our scheme and instead of trying to get a thumbnail, we will get a preview.
So we just change the options to get "-p" for preview and we run. And there we can see we have a nice preview of a recipe with all steps, the image and the name. And we are happy with that, so we can ship our plug-in. And we can go back to the slides.
So just to sum it up, when you want to create a Quick Look plugin, you create a new project from the template in Xcode. Then you define your document type in the Info.plist of the plugin. You implement both, or not, but it's better to have both thumbnail and preview functions. And you can change the attributes in your Ampho.plist. So if your code needs to be run in the main thread or not. Then you use QLManage to test it from Xcode. And to see all the options of QLManage, you can see its documentation.
And finally, you want to test it in real conditions, so you deploy your plug-in and you test it directly in Finder. And when you're good with that, you can ship it. So where do you go from here? Well, first, we want you to use to integrate Quick Look inside your application. If your application manipulates files, there are no reasons for you not to show the content of the files. And Quick Look is a great way to do this. So use the preview panel, use the preview view, use the preview controller.
In Mac OS X, ask Quick Look to provide thumbnails for all your files and documents. But don't be just a consumer, although be part of the process. If your application creates files, you should provide a generator for them. That will make your document visible everywhere in Mac OS X, from the Finder to Mail to all applications.
When you do so, make sure that your thumbnails look beautiful. You want them to look amazing in the Finder next to all other documents. And of course, make sure that you have good performances. Our computers are getting faster and faster, but we don't want to waste resources. If you need more information, you can contact our evangelist Bill Dernay or you can go to the usual Apple website. Thank you all for coming and have a great week at WWDC.