Say what I said before

A recent iOS project I’m working on has a feature to print PDFS. A search revealed that Apple had AirPrint as early as iOS 4.2. There isn’t much information online about AirPrint, so I wrote this blog post. Here is to share with you their own learning harvest.

content

1. What is AirPrint

  • In fact, the content on iOS (iPhone, iPad) is printed using a printer that supports AirPrint. Printing process wireless control, very convenient.

2. First-hand information

  • The first thing you’ll learn about iOS is the official Apple documentation. (The content I describe below is basically a summary of the document, English can be directly recommended to see the document…)

3, Printer Simulator, test using print Simulator

  • Since printing function is involved, it is necessary to have a printer that supports AirPrint function for testing. Do you not have one? It doesn’t matter! Apple has the emulator ready for us. This simulator is not available in Xcode, you need to download it from the official website:Download the Printer Simulator(Registration and login required)



4. See what AirPrint can print

  1. An array of ready-to-print images and PDF documents.

  2. A single image or PDF document. ,

  3. An instance of any of the built-in print formatter classes: print an instance of the formatter. (Simple text, HTML documents, some View displays).

  4. A custom page renderer: a custom page renderer Note: 1,2 is very simple, I will not explain in detail, 3,4 let’s translate this, do not understand it does not matter, continue to look down…


5. API of AirPrint

  • AirPrint’s API includes eight Classes and One Protocol. The diagram below shows the relationship between them. (The picture below makes sense, so you’ve got it.)

UIPrintInteractionController attributes:

  1. UIPrintInfo *printInfo: Prints information about a task.

  2. UIPrintPaper * printPaper: area for printing content.

  3. Delegate: observe UIPrintInteractionControllerDelegate agent agreement.

  4. The most important thing is to specify what you want to print: printingItem, printingItems, printFormatter, printPageRenderer. All four properties specify what to print. These four arguments are mutually exclusive, which means that if one is assigned, the other three arguments must be nil. It’s easy to understand, one printing task, can’t do more than one job at a time. This is easy to understand if you use the swift enumeration. The four properties of content mentioned here are related to point 4. The following table is the correspondence:

6. Printing process

  1. Create UIPrintInteractionController instance.

  2. Create UIPrintInfo instance. Output and configuration parameters of the output type (type), the print orientation (print), job name (print job id), and then assigned to UIPrintInteractionController instance printInfo attributes.

  3. To delegate attribute assignment, assign values must follow the UIPrintInteractionControllerDelegate agreement. This agent can respond to the printing Options screen showing and disappearing, the start and end of a printing job, and so on.

  4. Specifies what to print. PrintingItem, printingItems, printFormatter, printPageRenderer. One of the parameters

  5. Things get a little more complicated when you use printPageRenderer. You can draw the header, footer, and content of each page. This is where you count the pages yourself. In addition, you can also create one or more UIPrintFormatter as an example, through addPrintFormatter: startingAtPageAtIndex: Or the printFormatters argument can be assigned to printPageRenderer. Instance. You don’t have to count how many pages you have in this case.

  6. Finally, the Printing Options screen is displayed. Methods: on the device: presentFromBarButtonItem: animated: completionHandler: or presentFromRect: inView: animated: completionHandler:; On the phone: presentAnimated: completionHandler:


Said so much, the theoretical knowledge on the introduction of almost, the following code to demonstrate the specific implementation.

7,Printing printer-ready Content

  • AirPrint can print some content directly. These contents are instances of the NSData, NSURL, UIImage, and ALAsset classes, but the contents of these instances, or the referenced type (NSURL), must be image or PDF.

  • For image, the NSData, NSURL, UIImage, and ALAsset types all work. For PDF, only NSData, NSURL can be used. You then need to put these data instance directly assigned to UIPrintInteractionController instance printingItem or printingItems properties.

  • Print the PDF:

- (IBAction)printContent:(id)sender {
    UIPrintInteractionController *pic = [UIPrintInteractionController sharedPrintController];
    if  (pic && [UIPrintInteractionController canPrintData: self.myPDFData] ) {
        pic.delegate = self;
 
        UIPrintInfo *printInfo = [UIPrintInfo printInfo];
        printInfo.outputType = UIPrintInfoOutputGeneral;
        printInfo.jobName = [self.path lastPathComponent];
        printInfo.duplex = UIPrintInfoDuplexLongEdge;
        pic.printInfo = printInfo;
        pic.showsPageRange = YES;
        pic.printingItem = self.myPDFData;
 
        void (^completionHandler)(UIPrintInteractionController *, BOOL, NSError *) =
           ^(UIPrintInteractionController *pic, BOOL completed, NSError *error) {
             self.content = nil;
             if(! completed && error) NSLog(@"FAILED! due to error in domain %@ with error code %u",
                  error.domain, error.code);
        };
        if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
        [pic presentFromBarButtonItem:self.printButton animated:YES
            completionHandler:completionHandler];
        } else{ [pic presentAnimated:YES completionHandler:completionHandler]; }}Copy the code
  • Through the iPhone test, all the displayed is In English, do not worry, because this is the control of the system, that is to say, the system will automatically help you to do international processing, you do not use anything! All you have to do — will Info. The file first Localization of native development region (CFBundleDevelopmentRegion) value is set to China (zh_CN);


8, Using Print Formatters

Print Formatters Print Formatters Print Formatters

  1. UIViewPrintFormatter — Automatically lays out the content of a view over multiple pages. To obtain a print formatter for a View, call the view’s viewPrintFormatter method. Not all built-in UIKit classes support printing. Currently, only the view classes UIWebView, UITextView, and MKMapView know how to draw their contents for printing. View formatters should not be used for printing your own custom views. To print the contents of a custom view, use a UIPrintPageRenderer instead.

  2. UISimpleTextPrintFormatter – automatically draws the and lays out the plain – text documents. This formatter allows you to set global properties for the text, such a font, color, alignment, and line-break mode.

  3. UIMarkupTextPrintFormatter – automatically draws the and lays out the HTML documents.


  • The code for printing an HTML document is as follows:
- (IBAction)printContent:(id)sender {
    UIPrintInteractionController *pic = [UIPrintInteractionController sharedPrintController];
    pic.delegate = self;
 
    UIPrintInfo *printInfo = [UIPrintInfo printInfo];
    printInfo.outputType = UIPrintInfoOutputGeneral;
    printInfo.jobName = self.documentName;
    pic.printInfo = printInfo; UIMarkupTextPrintFormatter *htmlFormatter = [[UIMarkupTextPrintFormatter alloc] initWithMarkupText:self.htmlString]; htmlFormatter.startPage = 0; HtmlFormatter. ContentInsets = UIEdgeInsetsMake (72.0, 72.0, 72.0, 72.0); // 1 inch margins pic.printFormatter = htmlFormatter; pic.showsPageRange = YES; void (^completionHandler)(UIPrintInteractionController *, BOOL, NSError *) = ^(UIPrintInteractionController *printController, BOOL completed, NSError *error) {
             if(! completed && error) { NSLog(@"Printing could not complete because of error: %@", error); }};if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
        [pic presentFromBarButtonItem:sender animated:YES completionHandler:completionHandler];
    } else{ [pic presentAnimated:YES completionHandler:completionHandler]; }}Copy the code

  • Print out what is displayed on the UIWebView interface.
- (void)printWebPage:(id)sender {
    UIPrintInteractionController *controller = [UIPrintInteractionController sharedPrintController];
    void (^completionHandler)(UIPrintInteractionController *, BOOL, NSError *) =
        ^(UIPrintInteractionController *printController, BOOL completed, NSError *error) {
        if(! completed && error){ NSLog(@"FAILED! due to error in domain %@ with error code %u", error.domain, error.code); }}; UIPrintInfo *printInfo = [UIPrintInfo printInfo];
    printInfo.outputType = UIPrintInfoOutputGeneral;
    printInfo.jobName = [urlField text];
    printInfo.duplex = UIPrintInfoDuplexLongEdge;
    controller.printInfo = printInfo;
    controller.showsPageRange = YES;
 
    UIViewPrintFormatter *viewFormatter = [self.myWebView viewPrintFormatter];
    viewFormatter.startPage = 0;
    controller.printFormatter = viewFormatter;
 
    if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
        [controller presentFromBarButtonItem:printButton animated:YES completionHandler:completionHandler];
    }else
        [controller presentAnimated:YES completionHandler:completionHandler];
}

Copy the code

10, Using a Page Renderer

This part of the content is the most complex, feel not how to use, for the moment not to delve into, if the project needs, you can see the document.


conclusion

So far, the main technical points of AirPrint THAT I have learned have been shared with you. It can handle most of the requirements. If there’s something wrong there, you’re more than welcome to comment. In addition, I just started to write technical blog, and I’m not experienced enough. I hope you can give me more valuable advice.