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!
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!
Maybe someone (like me) needs to add border to the imageview before send it to the printer (otherwise the image will automatically fits to the sheet). I searched for some build-in methods in order to do this, but I haven't found it (btw, I read some hints from here).
The trick is to add the view containing the image to an external view, and then center it.
let borderWidth: CGFloat = 100.0
let myImage = UIImage(named: "myImage.jpg")
let internalPrintView = UIImageView(frame: CGRectMake(0, 0, myImage.size.width, myImage.size.height))
let printView = UIView(frame: CGRectMake(0, 0, myImage.size.width + borderWidth*2, myImage.size.height + borderWidth*2))
internalPrintView.image = myImage
internalPrintView.center = CGPointMake(printView.frame.size.width/2, printView.frame.size.height/2)
printView.addSubview(internalPrintView)
printController.printingItem = printView.toImage()
It's a little bit complex but it does its dirty job.