swiftuiviewairprintuiprintformatter

AirPrint contents of a UIView


I'm trying to set up printing through an iPad app, where clicking Print will print a view with all of its contents. Here's what I've tried (pulled together from a few examples online):

// This is the View I want to print
// Just a 200x200 blue square
var testView = UIView(frame: CGRectMake(0, 0, 200, 200))
testView.backgroundColor = UIColor.blueColor()

let printInfo = UIPrintInfo(dictionary:nil)!
printInfo.outputType = UIPrintInfoOutputType.General
printInfo.jobName = "My Print Job"

// Set up print controller
let printController = UIPrintInteractionController.sharedPrintController()
printController!.printInfo = printInfo
// This is where I was thinking the print job got the
// contents to print to the page??
printController?.printFormatter = testView.viewPrintFormatter()

// Do it
printController!.presentFromRect(self.frame, inView: self, animated: true, completionHandler: nil)

However, I also read here that viewPrintFormatter is only available to UIWebView, UITextView, and MKMapView, is that correct?

When I print with this (using the printer simulator) I just get an empty page; tried with various printers/paper sizes.

Any guidance is much appreciated!


Solution

  • I'm not sure if this is the proper way to do it, but I ended up solving this by converting the view to a UIImage and then setting it as the print controller's printingItem.

    Updated code:

    // This is the View I want to print
    // Just a 200x200 blue square
    var testView = UIView(frame: CGRectMake(0, 0, 200, 200))
    testView.backgroundColor = UIColor.blueColor()
    
    let printInfo = UIPrintInfo(dictionary:nil)!
    printInfo.outputType = UIPrintInfoOutputType.General
    printInfo.jobName = "My Print Job"
    
    // Set up print controller
    let printController = UIPrintInteractionController.sharedPrintController()
    printController!.printInfo = printInfo
    
    // Assign a UIImage version of my UIView as a printing iten
    printController?.printingItem = testView!.toImage()
    
    // Do it
    printController!.presentFromRect(self.frame, inView: self, animated: true, completionHandler: nil)
    

    The toImage() method is an extension to UIView:

    extension UIView {
        func toImage() -> UIImage {
            UIGraphicsBeginImageContextWithOptions(bounds.size, false, UIScreen.mainScreen().scale)
    
            drawViewHierarchyInRect(self.bounds, afterScreenUpdates: true)
    
            let image = UIGraphicsGetImageFromCurrentImageContext()
            UIGraphicsEndImageContext()
            return image
        }
    }
    

    Open to alternative approaches if anyone has one!