Video hosted by Apple at devstreaming-cdn.apple.com

Configure player

Close

WWDC Index does not host video files

If you have access to video files, you can configure a URL pattern to be used in a video player.

URL pattern

preview

Use any of these variables in your URL pattern, the pattern is stored in your browsers' local storage.

$id
ID of session: wwdc2012-234
$eventId
ID of event: wwdc2012
$eventContentId
ID of session without event part: 234
$eventShortId
Shortened ID of event: wwdc12
$year
Year of session: 2012
$extension
Extension of original filename: mov
$filenameAlmostEvery
Filename from "(Almost) Every..." gist: [2012] [Session 234] AirPrint.mo...

WWDC12 • Session 234

AirPrint

Essentials • iOS • 45:24

AirPrint is the iOS printing system, a revolutionary printing architecture that makes printing easy for users and app developers. Learn all about AirPrint and best practices for adding printing to iOS apps.

Speakers: Paul Danbold, Howard Miller, Todd Ritland

Unlisted on Apple Developer site

Downloads from Apple

HD Video (363.8 MB)

Transcript

This transcript was generated using Whisper, it has known transcription errors. We are working on an improved version.

Welcome to our WWDC 2012 printing session. I'm Howard Miller. I'm the engineering manager for printing. And I'm going to lead you through printing systems on Mac OS X and iOS and talk about AirPrint. So we'll start with an overview of AirPrint, our technology for printing. We're going to cover very briefly Mac OS X printing. We're going to spend a fair amount of time on iOS printing, which should help any iOS developer bring quality printing to their application.

Then we're going to show you some of the tools that we've developed that should help you debug printing applications on both platforms. So let's start with our printing architecture. Early in the days of Mac OS X, we introduced... the most advanced printing system on the planet. We provided two sets of rich APIs, Carbon and Cocoa, for your application.

We provided a comprehensive printing system, which wraps up the graphics capability of the Mac in a way that allows you to print that content. We layered it on a world-class spooling system. Many of you know that we use CUPS, the Common Unix printing system. And then we've provided a plethora of third-party printer drivers. In fact, Apple, Apple ships via software updates over three gigabytes of software drivers.

Starting in Lion, we introduced AirPrint to Mac OS X, which allows you to print without drivers. In Mountain Lion, we now prefer that as our default printing path, so you will get driverless printing on Mac OS X. For iOS, we brought the best of the printing system and our spooling system over. We used the same AirPrint architecture, and we provided a thin set of APIs, which will allow your apps to easily and quickly adopt printing. And that's where the bulk of today's presentation will be spent.

So on the OS X printing system, we provide an interesting user experience. We provide a simple mode by default. Users get the essentials of what they need to print. There's a more options, show details view where you now have a huge number of options that can go in front of the user.

About half of the users stay in the simple mode, the other half go to the advanced mode. Starting in Mountain Lion, as I mentioned, we will default for AirPrint printers to the AirPrint architecture, which means no drivers are necessary. If you use the legacy path, you have an older printer, we will continue to automatically download the drivers for the user.

The OS X printing experience is great for application developers. It is flexible and powerful. And if you want to know more about it, your best bet is to go on to the developer site, look at our sample code or buy just about any book on OS X programming and they'll cover printing. We're only going to touch on it briefly today. The OS was designed from the ground up to be easy to use. We wanted the user to be able to get consistent, high quality output without messing it up.

Too many options on other printing systems make it too hard for the user to get the wrong options. No drivers, there's no queues to set up, you pick your printer and print. In fact, you see here all of the options that we make available at print time to the users.

People often ask me, well, how does the user pick the paper size? And it may not have dawned on you, but the user picks the paper size down at Staples when they bought their paper. Why at print time do they need to tell your application or the printing system what size paper they are using? AirPrint and the architecture on iOS takes care of that.

The printer will tell us what paper size is loaded and at print time we will tell your application, render for that size. Smarter, more intelligent and easier to use for the user. And then we still provide the user with the best possible printer. We also provide for you an easy, simple way to add printing to your application. It is flexible and powerful and produces the same great quality output as we get from the desktop.

The AirPrint technology itself, again, was designed to provide a great user experience. It's available on all of our platforms starting with iOS 4.2 and in Mac OS X starting with Lion. It's standards based and it is a zero cost license for all printer manufacturers. As you know, we started in 2010 shipping printers from HP.

For those who are following, 2011, several other major manufacturers came online and we have licensed every major manufacturer on the planet, including some of the reference companies. CSR makes reference platforms for other printer companies and they will provide a complete AirPrint solution if you want to do a printer with AirPrint.

Speaking of AirPrint printers, it's pretty much been raining AirPrint printers this year and by June 1st, we have over 75 million AirPrint printers sold. If you go into your favorite electronics store and you buy a printer, you may not even realize it, but the vast majority of consumer ink jets and laser printers are AirPrint and AirPrint is expanding into the larger lasers and wider formats as we see. Thank you. Thank you.

As you design your application, you're going to take care of all your user requirements and you probably, as you get to the end, start thinking about printing. Maybe you think about it at the beginning, that's why you're here, and we thank you for that. A print experience is designed for paper, not for the display.

An 8.5 by 11 piece of paper has higher resolution than even our new MacBook Pro Retina display. You have to plan ahead. You have to provide your assets in a form that's of high quality. You should draw with vector when you can. You should make sure that you provide the correct size icons. You can archive all that so it's not taking a lot of space. But plan ahead for paper. And I just have to come back to the big point. WYSIWYG was so 1985.

In today's world, design your app for the screen real estate and make it look great. And then design your output for paper and make it look great. Those two are not going to be the same. Here is a great application, Quicksail. Great user experience they've put forth here. On the screen, they've made great use of all the real estate of the iPad. You can select what items. It makes sort of a punch list, gives you the price. You can put in discounts. It gives you the tax.

A total is there, but you're not going to give your customer the iPad and say, here, mail me a check. No, you're going to mail your customer an actual invoice. And this is a... An invoice, they took the same information that you see on the screen. They formatted it for print onto this invoice, which demands payment. So, as you're working on your app, design it for the screen, make it beautiful. And when you go to print, design it for print and make it beautiful. Let me talk just briefly about OSX printing.

There are no changes. So if you have an app that prints on Mac OS X, it should continue to print on Mac OS X today. I would, however, ask you to think about what APIs you were using. The OS has gotten pretty mature at this point, and many APIs throughout the entire operating system have been deprecated, and we continue to see some of these deprecated APIs used.

So take your application, recompile it on a clean version of Xcode on Mountain Lion, and all of those warnings or errors that you get, fix those. It's not just going to be printing. It may be across your application if it's an older application. Clean it up. Make sure your app remains modern, because some of these APIs do disappear in future versions of the OS. So that's everything you need to know about Mac OS X.

Go buy a quality book or go to our developer website. If you have an existing app, just recompile it. Make sure life still looks good. With that, we're going to get to the focus of today's meeting, which is what does it take to make your iOS app print beautifully? And with that, I'm going to bring up Paul Danbold, who will drive you through the details of our API. So Howard had one slide on OS X printing. I've got a few more to talk about iOS printing.

But let me start with just emphasizing a point that Howard made, and that is iOS printing is easy. Easy for users, because a few taps on screen gets what they want from your apps onto paper. But easy for you, because with a few well-designed APIs and a very little bit of code, which we'll see in a few minutes, you can add supporting to your apps, printing support to your apps.

So a quick rundown of the UIKit printing classes. This won't take a moment. The print interaction controller is the controller for running a print job. It has the methods to bring up the user interface for printing. It brings together the metadata for any print job, the content to be printed. It has a couple of informational classes.

UI Print Info encapsulates information about any print job, its name, whether the job's coming out portrait or landscape orientation, one-sided, two-sided, and those sort of settings. And then you have UI Print Paper, which describes basically a sheet of paper and the printer's hardware margins for that paper size. And the hardware margins dictate where you can draw your content.

We have these formatter classes that know how to deal with simple text, markup text, web views, and text views. And you'll use those for that kind of content. And then last on this list, we have UIPrintPageRenderer. It's an abstract base class. You'll subclass it when you want to take full control over page layout.

Here's how you print. Pretty straightforward. You get the print interaction controller. It's a shared object, so no need to allocate it. You set on the controller the content you want to print. This could be as simple as providing a PDF file or a JPEG image. It could be one of the formatter objects that we mentioned on the previous slide, or it could be a custom page renderer that you created.

You tell us about the output type. This is very important because the settings appropriate for printing, let's say, a photo are very different from the settings appropriate for printing, let's say, a web page or a simple text document. You give every print job a meaningful name, a user-visible name, in case the user wants to find that job in the print queue on the device.

and last you present the UI for printing, or you tell us to present the UI for printing. From there we handle interaction with the user, prepare the print job, talk to the printer to get it processed. Now in iOS 6 you can use the activity view control for printing, and I'll talk about that later, and in that case the steps are a little different, but for the most part you'll be following this sequence to print your content.

Here's a little bit of code to show you what's involved. We're going to print a PDF. It's a good idea to check before you proceed down the rest of the code here that the content you're going to provide us to print is, in fact, printable. So if you provide us something in an unrecognized format or the data is corrupted, for example, there's no point going on. But if you're okay, you get the print interaction controller, shared object. You set on the controller what you want to print. In this case, it's the PDF URL.

You obtain a print info object and here you can see you're setting the output type, which is telling us about the content to be printed, and you're setting the job name to the URL for the PDF. And you set that print info on the controller, makes a copy of it, and it uses that when the UI comes up and when the print job is generated.

If you're going to print a multi-page document, it's a good idea to set the show page range option on the controller, which means that the user will see the page range option in the printing sheet in case he or she doesn't want to print every page in the job. And last, you tell us to bring up the UI for printing. This is the code that you'll use on iPhone. It'll bring up the printing sheet. If you're on the iPad, you'll do something slightly differently. But that's all there is to it.

So I mentioned output type. And if you're using OS X or most other platforms, you're used to having a print dialogue where the user can manually select a paper size, a media type, a quality mode, and that sort of thing. But we like to make life a little simpler for the user of iOS devices. And generally speaking, your apps know what you're printing. You know that you're printing a photo or a web page, for example.

So by telling us the output type, in other words, telling us about the content that you're going to give us to print, we can make smart decisions about the paper size to use for the print job, the quality mode appropriate, and the options appropriate for printing that kind of content in the UI.

We've defined three kinds that you can specify. If you set the output type to UIPrintInfoOutputPhoto, we tell the printer to print in its highest quality mode. And we use a photo paper size if available, and if the printer can print borderless, it'll do that for this kind of content. There's no point in offering two-sided printing for photos, and for that matter, there's no point in offering a page range control in the interface because it's one photo per sheet of paper.

Second kind we've defined is UI print info output general. So a web page falls into this category, mixed text and graphics. And for this kind of content, there's no point in asking the printer to print in its highest quality mode. And the paper size associated, sorry, paper size appropriate for this kind of content would be letter or A4. If the user selected printer has a duplexer, we enable the user to pick one-sided or two-sided output. And if you set the page range option on the controller, we allow the user to pick a page range for the print job.

The third kind is UI PrintInfo output grayscale. This may be the best option to use if you know there's no color content to be printed. We ask the printer to print in a faster print speed in a way that reduces ink or toner usage. Document page size makes sense in this case, so again letter or A4, and we conditionally enable duplex and page range as we did with UI PrintInfo output general.

We can find out from any printer which paper sizes it supports, but that's a very different matter from actually knowing what paper sizes are loaded at print time. We're actually working with the printer manufacturers to bring to market printers that can sense and report to us the sizes of papers loaded in the paper trays.

When they do that, we can, in many cases, just automatically pick the correct paper size to use for a print job. Or, in some cases, we can present to the user the available paper sizes to choose for a print job. And we do this in the case of printing photos. I mentioned job name a few slides ago. So the user can see the queued jobs on their device and they can get information about any job. So it's helpful if you help your users identify print jobs that came from your app.

So the code example we had for printing a PDF was an example of what we call printing items. And printing items means printing content that's already in a format well suited for printing. So that's PDF, JPEG, other image types that ImageIO knows how to support. All you have to do is set one of those items on the interaction controller, tell us the output type, give the print job a name, and we take care of the rest for you.

If you're pulling a picture out of the photo library with the image picker, you don't even need to load the image into your app, just send us the URL. And you can hand us an array of items to print. And the array doesn't even have to contain all items of the same format. And we'll print one, each one of those items in the array as a print job in itself.

So, four matters. This is all about printing simple text, HTML, markup text, web views, and text views. As you probably know, if you've got that kind of content and you're trying to draw it into a particular area, let's say a particular paper size, a particular page orientation, it's a lot of work to figure out where to do your line breaks and your page breaks. But formatters take care of all that complexity for you. You can use a formatter standalone, setting it on a print interaction controller if you've just got, say, a plain text document to print or a web page to print. Or you can associate formatters with print page renderers.

And I'll talk about that in a few minutes. If you want to use a simple text formatter, setting it on the print interaction controller, you get to choose the font, the color, the text alignment. And if you're using the markup text formatter, you're using the same HTML rendering engine that Safari uses.

Again, not a lot of code involved. We've got the Print Interaction Controller, and here you're creating a markup text formatter, handing it maybe some HTML that you generated or was downloaded, for example. You set it on the controller. You set up your PrintInfo object and put that on the controller. Tell us to bring up the UI, and that's all there is to it. Almost no code.

Just a couple of diagrams to talk about where the formatters lay out their content. So we've got the paper rect, which represents the physical sheet of paper, origin 00. And inside there, you've got the printable rect, which is the area dictated by the printer's hardware margins for that paper size.

And by default, the formatter is going to draw its content into that printable rect. But you can adjust the area in which the formatter draws its content. And there's a few cases where you might want to do that. And the most common one is where you're using formatters in conjunction with a print page renderer. And you want formatters maybe to draw their given content in assigned little rectangles at various parts of various pages in the print job.

When you're doing something like that, you need to constrain the area in which the formatter does its drawing. And you can do that with content insets. And as you can see here, you can specify a top, left, and right inset from the printable rect. And the formatter will start drawing into that rectangle.

But you don't set the bottom inset, because the formatter will carry on drawing until it gets to the end of its content, which may involve going over multiple pages. And note that the top inset applies to... just the first page on which the formatter starts doing its drawing.

I was talking about using formatters for simple text and markup text, but you can also use formatters for web views and text views. And it's as simple as, as you can see here in the code, just asking for a view print formatter for, in this case, a web view.

And once you've got that formatter, you set it on the print interaction controller and it's the same kind of code as you've seen before. All very straightforward. You can ask for a view print format of other kinds of views and we'll return a generic formatter, but generally that wouldn't be the recommended technique. It would be better to use a print page renderer and do the drawing of those views yourself.

So, formatters are for simple text, markup text, web views, and text views. Print page renderers. So, you know, Howard was talking about designing for paper. You know, what you present on screen doesn't necessarily make sense or doesn't necessarily take full advantage of what you can put on paper.

And for that matter, the way you present your content on iPhone screen may be different from what you do on the iPad. So for paper, you want to think about the best way to present your content. And when it comes to taking full control of a page layout, this is where print page renderers come into play.

They give you full drawing control, in other words, full control over what goes where on the paper. And what you'll do is you'll subclass the UI print page renderer base class to create a custom page drawing object. And we're going to ask you to do two things. One, calculate and tell us how many pages are going to be in the print job. And two, we're going to call you to draw each page in the print job.

We let you designate an area at the top and bottom of every page if you want to draw, for example, a header, a title string at the top of every page, and a page number at the bottom of every page. And we let you assign formaters to a print page renderer. You can have multiple formaters all drawing their given content in various places on the page. And if you specified headers and footers, we'll make sure the formaters don't draw into the areas reserved for those headers and footers.

Here's what you'll do. You'll subclass UI print page renderer. It's got a lot of functionality, but you're going to need to override number of pages. When the user picks the printer, you've told us the output type, we'll select a paper size appropriate for the content, and we'll return to you that paper rect and printable rect. You know your content, you calculate and tell us how many pages are going to be in the print job.

and then you're going to implement draw content for page at index in Rect. That's where we're going to call you to draw each page in the print job. And having created your custom print page renderer, you're going to set it on the controller just in the same way as you saw before when we were putting a format or printing item on the controller.

Another diagram, so we have the paper rect, the printable rect, and optionally, you can specify a header height and a footer height. And those are either for you to draw your titles and your page numbers, or just to impose a top and bottom margin on every page that's maybe larger than the hardware margins dictated by the printer. Between the header and the footer, you've got the content rect.

and set the stage for a little bit of code. We won't have a header and a footer in this example. We've just got a bunch of graphics to draw, like a table view, down the page. And to make our code simple, all those items have the same height.

Here's your print page renderer. We've got a method here that we're going to call to draw each graphic going down the page. Because each one of those graphics has got the same height, we can easily calculate just once how many can fit on a page. Then we've got the methods we're going to override: number of pages and draw content for page at index in rect. Here are the overrides.

We don't have a header or a footer, so we just divide the height of those graphics into the height of the printable rect. We know how many items we've got to print, so we can calculate how many pages in the print job. In the override for draw page at index, sorry, draw content for page at index, you need to set the clip to the content rect because we don't clip by default for you. And then you're going to be calling your method to draw each of those graphics, one after the other, iterating through the array along the way, calculating the offset relative to the origin of the content rect. Again, not a lot of code.

The PrintPageRenderer class has got a number of methods that you can override. Draw page at index in Rect is the main entry point. And most apps won't want to override this. But if you wanted to take complete control of drawing everything on the page, you could override draw page at index in Rect.

Otherwise, it's going to invoke the methods listed below in the order in which I've listed them. If you set a header height and if your print page renderer subclass implements drawHeaderForPageredIndex, then we'll call you to draw that title string at the top of every page. And similarly for the footer, your subclass will implement drawFooterForPageredIndex.

Most of the work is likely to happen in draw content for page at index in Rect, and that's the code that you saw on the previous slide. Now if you've associated formatters with your print page renderer, the print page renderer class is going to call draw print formatter for page at index to get the formatters to do their work.

And for the vast majority of apps, you wouldn't override this method. But a case of when you would want to do that is if you wanted the formatters to do their drawing and then you wanted to draw content after, effectively on top of what the formatters had drawn.

Okay, so we've covered printing items, using formatters, and doing custom layout with print page renderers. I'm going to talk about a few topics that are associated with the user interface for printing. So the standard ways of bringing up the interface for printing on the iPhone here, you've got present animated with a completion handler to bring up the sheet for printing. On iPad, to bring up the popover for printing, you can either bring it up from a location in a rectangle on a view, present from rect in view, or from a bar button item.

But maybe you want to embed our printing UI in some UI you have. And the screenshot here is from Apple's Pages app. And you can see it's got a share and print nav controller with print as one of the items. So if you want to do that, you'll implement print interaction control parent view controller, the delegate method. When you call one of those present methods that were on the previous slide, we'll invoke your delegate to get the view controller.

If you've got a nav controller, we'll call it push. If it's a view controller, we'll call it present modal. And basically what's going to happen is, as you can see here, we'll slide our printer options UI into your UI. The back button comes from the app, but at this point the user can select their options to print. Now, you've got access to our view controller, but don't peek. Don't make any assumptions about the UI we present, because sooner or later we'll change our UI and the consequences for your app aren't going to be good.

Another thing Howard was talking about was the fact that printing in iOS is what we call dynamic. It's not whizzy-wig. What you see is what you get most of the time. And you're going to, for the most part, sorry, the vast majority of apps are going to let the user pick a printer, tell us the output type, get back a page size, and then make your layout decisions. There's no page setup dialogue or anything like that. But there are a few apps whose purpose is to enable the user to create a document for a particular paper size. And this is what Pages does.

So it allows the user to choose between US letter or A4. So if you're going to do something like this, if you want to get involved in paper size selection, you're going to have to provide your own UI. And you're going to have to get involved in the process of picking from the printer's list of papers one that's a good match for the paper size your user selected in your app.

You do that with this print interaction controller delegate, choose paper. It gets called after the user picks a printer and we provide the list of papers that the printer says it supports or even better, for printers that can report their loaded paper sizes, the list of loaded paper sizes. You've got the paper size that the user selected and you want to find one from the printer's list that's a good match.

Here's a contrived implementation of choose paper. Let's say you want to find a US letter, 8.5 by 11 inches in points. We provide class method on UIPrintPaper, best page for page size. You hand in the paper size you want, along with the printer's list of paper sizes, and we return a UIPrintPaper that's a good match. and that's the one that will be used for the print job.

Now, last but not least, there's the activity sheet new in iOS 6. And if you have content to print that's appropriate for not only for printing, but for using by the other items shown on the screenshot here, then printing by the activity sheet may be the best way of printing and the easiest way of printing from your app.

There's no print interaction controller in this kind of printing, so there are a couple of restrictions currently using the UI activity view controller. You don't have a way of allowing the user to choose a page range, and because there's no print interaction controller delegate, choose paper, you can't get involved in paper size selection.

To give you an idea of the code involved, you've got an array of activities, activity items, basically the items you want to share. So print, mail, and the other things that you saw on the screenshot on the previous slide. What you're going to do is you're going to provide, in this case, an instance of a custom print page renderer object that you set up, the print info containing the settings for the print job, and what you want to print, in this case, let's say a web page.

If you wanted to, instead of a print page renderer, you could set a formatter here or a printable item. But basically when you present your view controller, the user can see mail, print, etc. If they tap on print, we're going to compose a print job using your custom print page renderer, the print info you've provided, and the content, create a print job and process it. Alternatively, if the user tapped on mail, then we can compose a mail message with that same web page.

Okay, so that's printing items, formatters, print page renderers, and a few UI considerations. Hopefully you got the message. It's all very easy and straightforward. I'm going to hand you over to Todd to talk about the printer simulator. Thank you. I'm Todd Riitland, a printing engineer. So you just saw a lot of information about all the different APIs for printing on iOS. If you're new to this, you might be wondering, "Well, how do I start?" 'Cause that's a lot of information.

Another good question that developers ask themselves is, what tools are available to help make my job easier? We've developed a tool to help you make putting printing into your app a lot easier, and it's the printer simulator. It creates virtual printers on your Mac, so you can avoid wasting paper as you're developing your application.

It outputs PDF representations of what would actually go on a printed page. We actually use this as our reference implementation for AirPrint. So it's not a trick, we're not faking anything. It's actually the entire AirPrint protocol from the iOS device or the iOS simulator to the printer simulator. And I'll show it to you right now.

Okay, so we have Mountain Lion here with the seed version of Xcode. And I have downloaded the print web view sample. This is available on Apple's developer connection website. It's a great example. If you're just starting out, it has formatters and renderers. So we'll just double click it, open it up in Xcode.

So I've chosen the iPhone simulator. We'll just click run. And there we have it. It's a pretty simple UI. It's just a text field where you enter a URL and a web view that has content and then a little share button here to print. I'll tap this to bring up the printing UI.

So right now we don't have any AirPrint printers. There shouldn't be any around here. And that's where the printer simulator comes in. So to access the printer simulator, in the iOS simulator, we go to file, open printer simulator. And we just tap that. And then this is our printer simulator. Because we use Bonjour, the printers will just pop up right in our UI here. So I'll choose to select the simulated laser.

Tap print. And output, there's our output. So you notice a few things here. The yellow that's around the edge of the sheet represents the unprintable area. This is the printable rect that you saw Paul mention earlier. So I actually inserted a bug into the sample, which is why we see here this header is going off the page and it's in this unprintable area.

So that's not what we want. So we'll go back into our sample. Luckily, I know exactly where to fix this. In our MyPrintPageRenderer, we have a couple of defines. Header left text inset I changed to negative 20. Should be positive 20. So I'll save that change. We'll click run.

So we'll do the exact same thing again. Tat print. And there we have our corrected output. So the header is in the right place. Everything looks good. And so we're good to go. So this is a simulated laser. It's a black and white laser. The other simulated printers that are available, we have some inkjet printers, which actually do the iOS device does the rendering. We have Save Original, which is a special queue, or a special printer that will actually preserve... Someone else is printing to my printer simulator.

The save original will preserve your content if you're printing items, JPEGs or images. It will save that original and open it up in preview. Or if you're drawing using print page renderer or formatter, we'll capture those into a PDF in its original form. So if we choose that and click print, we'll notice if we zoom in here, we have We can select the text. You can zoom in and see unrasterized content. So if you're doing custom drawing, you can zoom right in and see exactly, you know, if your corners are matching, if you're closing loops and things like that.

So there's a few preferences that will help with testing in Printer Simulator. And we go to Printer Simulator Preferences to take a look at those. So you can choose to save the print jobs on your desktop or some other location. By default, they don't get saved, so when you close the app, they all disappear.

You can turn on and off "show printable area." This is that yellow area around the edge of the page. and you can turn on simulate print times to slow down to actually simulate the real timing of a printer. This might be helpful if you print center, if you want to take a look at print center to see your job name.

Normally the printer simulator goes so fast you don't get a chance to look at print center to see the job. So if you want to make sure that your names are showing up correctly, you can turn on simulate print times. So as I mentioned, using it for testing, we recommend that you use all four of the simulated printers.

Save original is good while you're developing your app. For testing, we think you should use all four. Each one has different margins, different characteristics, different resolutions. Some support duplex, some don't. When you print duplex, some printers even change the margins. This is pretty typical of inkjet printers. So you actually get quite a bit of testing, quite a bit of coverage just by using all four of them.

and any content in the yellow area of the page will be collected by the printer. One thing I wanted to mention is printer simulator is great for testing but it doesn't substitute for using a real printer. It's important that you use real printers so you see what your output looks like so you get a sense of how it's going to behave with your app.

For anyone familiar with the printer simulator may have noticed a new button. It's new in the iOS 6 SDK. It's a load paper button. Now, I'm have you wondering, load paper? I thought this was a simulated printer. Is this some kind of like a Zynga game where you have to load, you know, virtual paper? It's not. It's actually -- this represents paper-sized sensors, as has been mentioned before. A lot of AirPrint printers in the future will have these paper-sized sensors.

This is how the user selects the size that they want, is they put the paper into the printer and the sensors will tell the system what size to use. So if your app prints items, the operating system will automatically size the PDF or photo to whatever is loaded. If your app uses formatters or renderers, the paper rect and the printable rect will represent the size that's loaded at the printer.

This is the printer simulator UI for selecting these different loaded papers. We have one drop down for each tray. And I'll show that to you right now. So we'll click on this load paper button and here's the UI that I was mentioning before. So for the simulated laser, we'll go ahead and choose change U.S. letter to U.S. legal, which is 8.5 by 14.

We'll do the same thing that we did before, choosing a simulated laser. and we'll see that now our output is on 8.5 by 14. Just to show that again, we'll look at a little bit longer website. And there we have a legal page. So there's a little bit of difference in the UI, as Paul mentioned, when you're using photo output type. Print photo is another developer example we have that prints photos, so we'll go ahead and look at that.

When a printer says it knows what size it has loaded, if there are more than one size and we're printing a photo, that's the only time that we'll show this paper UI for the user to select paper. Because we really don't know which size the user would want to print their photo on. So in this example, we're printing to our laser. Let's say that we want to choose legal. This is what it would look like if a user was printing a photo to a black and white laser on legal.

So as I mentioned, the printer simulator is a complete AirPrint -- it implements the complete AirPrint protocol, so it'll work on a local network with any iOS device, as we saw earlier. Some people in the audience were using it. So we can actually, you can use your real iOS device. I'll close this. You can use a real iOS device if you're just on the same network. You can test. It works with that and the iOS simulator.

As Howard mentioned, we have Mac OS X now supports printing directly to these AirPrint printers from Lion on. In Mountain Lion, it's the default. So let's see how that works. Because we have our printer simulator running, we should be able to use it right from here. So all we do is select. The printer, it automatically figures out everything that it needs. It'll get the icon. We can even get supply levels. This is a simulated supply level. So you get a full printing experience to these AirPrint printers. We just click print. And there we have our output.

So this is pretty powerful. On both Mac OS X and iOS, all you need to do is select your printer and tap print. There's no extra setup, there's no drivers to download. It happens nearly instantaneously. and that's a pretty cool thing. So with that, I'll give it back over to here, Howard.

So you've seen the overview of our AirPrint technology. It's very pervasive in the market at this point. It is the only supported printing technology from iOS. It's now the default print path on Mac OS X. If you're a Mac OS X developer, just recompile your program. Make sure you don't have any deprecated APIs.

If you're an iOS developer and you're looking to bring printing to your application, we have a lot of sample code available. It's very simple. If you're printing items, a matter of 10 or 12 lines of code and you are good and done. If you're writing a full-fledged application that requires detailed printing, Paul's given you a great overview of formatters and print renderers, which should allow you to create desktop-quality printed output. And then as Todd has shown you, we've created this printer simulator, which will let you print your own printer. It will let you, in development, simulate typical printers, both inkjet and laser.

And it's also a tool that's very useful in your QA process. We recommend that you buy a few AirPrint printers, but you should be able to get a lot of your work done without having to waste any paper. In terms of resources, Paul Danbold, our evangelist, is always available to you. We have a complete set of iOS printing documentation developed on developer.apple.com. And then of course, we have several bits of sample code that will show you how to use everything for iOS printing. Same website has samples and documentation for OS X printing.

Of course you should subscribe to the developer forums if there are questions about printing, many of us are there to answer. And if you're interested in AirPrint or in particular what AirPrint printers are available today, we keep a comprehensive list in this AirPrint 101 knowledge base article. If you missed it, you can go back to the videos and you can see the Cocoa Touch class, which covers some interesting elements related to UI. And with that, we hope you have a great WWDC. Thank you for being here.