AirPrint contents of a UIView
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!
Printing the view in iOS with Swift
I have found the answer to my question by modifying the code found here: AirPrint contents of a UIView
//create an extension to covert the view to an image
extension UIView {
func toImage() -> UIImage {
UIGraphicsBeginImageContextWithOptions(bounds.size, false, UIScreen.mainScreen().scale)
drawViewHierarchyInRect(self.bounds, afterScreenUpdates: true)
let image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return image
}
}
//In your view controller
@IBAction func printButton(sender: AnyObject) {
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 = self.view.toImage()
// If you want to specify a printer
guard let printerURL = URL(string: "Your printer URL here, e.g. ipps://HPDC4A3E0DE24A.local.:443/ipp/print") else { return }
guard let currentPrinter = UIPrinter(url: printerURL) else { return }
printController.print(to: currentPrinter, completionHandler: nil)
// Do it
printController.presentFromRect(self.view.frame, inView: self.view, animated: true, completionHandler: nil)
}
Air Printing of a UIView generates white pages
FWIW here's complete working code to print a bitmap from any UIView from iPad/iPhone
NOTE, THIS ONLY PRINTS A BITMAP.
Note that (bizarrely) iOS seems to NOT INCLUDE the concept of rendering a UIView to postscript .. Print a UIView, but NOT by rendering as a bitmap image
In other words the following seems to be meaningless in iOS, as yet...
UIViewPrintFormatter *f = [self.view viewPrintFormatter];
Anyway the following will print (JUST AS A BITMAP) absolutely any UIView whatsoever...
You simply use renderInContext: or,
for more modern code,
the combination drawViewHierarchyInRect: and UIGraphicsGetImageFromCurrentImageContext()
- (IBAction)printB:(id)sender
{
// we want to print a normal view ... some UILabels, maybe a black line
// in this technique, depressingly we CREATE AN IMAGE of the view...
// step 1. make a UIImage, of the whole view.
UIGraphicsBeginImageContextWithOptions(self.printMe.bounds.size, NO, 0.0);
// [self.printMe.layer renderInContext:UIGraphicsGetCurrentContext()];
// UIImage *asAnImage = UIGraphicsGetImageFromCurrentImageContext();
// .... or, more futuristically.....
[self.printMe drawViewHierarchyInRect:self.printMe.bounds
afterScreenUpdates:NO];
UIImage *snapshotImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
// step 2. choose grayscale, etc
UIPrintInfo *info = [UIPrintInfo printInfo];
info.orientation = UIPrintInfoOrientationPortrait;
info.outputType = UIPrintInfoOutputGrayscale;
// step 3, print that UIImage
UIPrintInteractionController *pic =
[UIPrintInteractionController sharedPrintController];
pic.delegate = self;
//pic.printingItem = asAnImage;
pic.printingItem = snapshotImage;
pic.printInfo = info;
UIPrintInteractionCompletionHandler completionHandler =
^(UIPrintInteractionController *pic, BOOL completed, NSError *error)
{
if (error)
NSLog(@"failed... %@ %ld", error.domain, (long)error.code);
if (completed)
NSLog(@"completed yes");
else
NSLog(@"completed no");
};
[pic presentAnimated:YES completionHandler:completionHandler];
}
It's really that simple, fortunately. But it is a rendered bitmap image.
How to print a UITextField text by AirPrint
From this, the printingItem
:
The object must be an instance of the
NSURL
,NSData
,UIImage
, or
ALAsset
class.
so probably you have to pass something like:
NSData* data=[_txtmainnote.text dataUsingEncoding:NSUTF8StringEncoding];
print.printingItem = data;
Related Topics
How to Observe Array Property Changes in Rxswift
Converting Audiobuffer to Cmsamplebuffer with Accurate Cmtime
Realitykit - How to Edit or Add a Lighting
Adding a Custom Font to MACos App Using Swift
Create a Swift Dictionary Subclass
How to Override Private Method and Call Super in Swift
Swift Protocol with Associated Type - Type May Not Reference Itself as a Requirement
How to Test Asynchronous Methods Swift
Swiftui Hierarchical Picker with Dynamic Data
Hide Status Bar in Launch Screen
Swift Memory Management: Storing Func in Var
How to Process an Array of Task Asynchronously with Swift Combine
Swift: Copy Information Selected by User in Abpersonviewcontroller to Dictionary
How to Create Public Extensions, in a Shared Framework, for Xctest
Why Does Type(Of:) Return Metatype, Rather Than T.Type
How to Set Interactive Push Notifications on iOS8