Including AirPrint on an iOS App

Guides By 5 years ago

AirPrint on iOS is an attractive feature to include these days as more printers become AirPrint enabled, and it certainly makes sense to include it in some Applications.
Thanks to Apple’s APIs, using AirPrint in code is a trivial task, you simply have to sign up for delegate notifications from the AirPrint view controller, show or hide the view controller when it suits you, and tell the view controller what you would like printed. To start off, declare that you will use the UIPrintInteractionControllerDelegate in your view controller like so:

@interface SomeViewController : UIViewController 
{
}

In the .m of your code, handle the necessary delegate methods:

#pragma mark -
#pragma mark UIPrintInteractionControllerDelegate

-(UIViewController*) printInteractionControllerParentViewController:(UIPrintInteractionController*)printInteractionController
{
	return nil;
}

-(UIPrintPaper*) printInteractionController:(UIPrintInteractionController*)printInteractionController choosePaper:(NSArray*)paperList
{
	return nil;
}

-(void) printInteractionControllerWillPresentPrinterOptions:(UIPrintInteractionController*)printInteractionController
{
}

-(void) printInteractionControllerDidPresentPrinterOptions:(UIPrintInteractionController*)printInteractionController
{
}

-(void) printInteractionControllerWillDismissPrinterOptions:(UIPrintInteractionController*)printInteractionController
{
}

-(void) printInteractionControllerDidDismissPrinterOptions:(UIPrintInteractionController*)printInteractionController
{
}

-(void) printInteractionControllerWillStartJob:(UIPrintInteractionController*)printInteractionController
{
}

-(void) printInteractionControllerDidFinishJob:(UIPrintInteractionController*)printInteractionController
{
}

Although I haven’t written any code here, you can see that its trivial to program reactions to events in printing (like when it finishes or starts a print job). So that’s the delegate, but you will also have to program the main print view controller in the .m. Since the print view controller is shared you can simply get a valid instance like so:

UIPrintInteractionController* printController = [UIPrintInteractionController sharedPrintController];

Next we will have to put any data we want to print into an NSData, this is commonly PDF’s or images in common formats (jpeg and png), to format text I often generate a PDF, although there are other ways to go about this (UISimpleTextFormatter).

NSString* pdfFile = [[NSFileManager defaultManager] documentPath:@"test.pdf"];
NSData* pdfData = [NSData dataWithContentsOfFile:pdfFile];

Now the data we want to print is contained in the NSData object pdfData, we can check whether the AirPrint driver will recognise it:

if(printController != nil && [UIPrintInteractionController canPrintData:pdfData])

If it can print the data, we simply need to create a UIPrintInfo object, which will tell the printController about the job name, the output type and the duplex (you can specify other features such as orientation):

UIPrintInfo* printInfo = [UIPrintInfo printInfo];
printInfo.outputType = UIPrintInfoOutputGeneral;
printInfo.jobName = @"test.pdf";
printInfo.duplex = UIPrintInfoDuplexLongEdge;

After we have created this object, we assign it to the printController and set up the delegate:

printController.delegate = self;
printController.printInfo = printInfo;
printController.showsPageRange = YES;
printController.printingItem = pdfData;

Next we have to present the UIPrintInteractionController to the user so they can select which printer to use. This method varies from iPhone/iPod to iPad, on the iPhone/iPod you would simply present it like you would any modal view controller:

[printController presentAnimated:YES completionHandler:^(UIPrintInteractionController* printController,BOOL completed,NSError* error)
{
	if(!completed && error)
	{
		NSLog(@"Error: %@",error);
	}
}];

This will bring the UIPrintInteractionController modal view over your current view, to use it on the iPad you will have to specify where you want to show it on the screen, you can do it via a specific coordinate or a Bar Button Item:

[printController presentFromRect:sender.bounds inView:sender animated:YES completionHandler:^(UIPrintInteractionController* printController,BOOL completed,NSError* error)
{
	if(!completed && error)
	{
		NSLog(@"Error: %@",error);
	}
}];

In the above I used the object “sender” to align the UIPrintInteractionController, this is because I often like to present it over a UIButton in a touch event, and this simply lets me present it exactly where the button is. If your code has got to here, you should be seeing a UIPrintInteractionController. If not, it could be possible your device doesn’t support AirPrint. To check this, simply call the following method:

[UIPrintInteractionController isPrintingAvailable];

I would strongly encourage anyone reading this to implement AirPrint where applicable. Apple is trying to make the move towards driverless printing which is a very tricky and noble one, and the more applications that support AirPrint the more manufacturers will be encouraged to support this kind of technology.

  • any idea how to capture a javascript call to window.print from inside a UIWebView? I don’t seem to be able to invoke any printing if the call is initiated by clicking a print button in a uiwebview that makes the request via javascript