Hello, I am wondering is anyone has been able to successfully print to a custom paper size using UIPrintIneteractionController, or if it is even possible. Apple seems to think that only the standard size paper for your machine's local matter. Unfortunately, not all print jobs are for predefined standard paper sizes.
What i am attempting to do:
Print a PDF, that is 5.66" x 11", or ~408pts x 792pt, on a sheet of paper that is the of the same dimensions.
What I have tried:
Attempt 1:
I have used the UIPrintInteractionController in it's most basic form, allowing a user to select the paper size. As expected, this did not match the size required because the desired size was not offered as an option
Basic UIPrintInteractionController implementation:
if UIPrintInteractionController.canPrintURL(pdf!.localPDFUrl!) {
let printInfo = UIPrintInfo(dictionary: nil)
printInfo.jobName = pdf!.localPDFUrl!.lastPathComponent!
printInfo.outputType = .Photo // .General
printInfo.duplex = UIPrintInfoDuplex.None
let printController = UIPrintInteractionController.sharedPrintController()
printController.printInfo = printInfo
printController.showsNumberOfCopies = false
printController.printingItem = pdf!.localPDFUrl
printController.presentAnimated(true, completionHandler: nil)
}
Attempt 2:
I have let UIPrintIntereactionController do it's thing by attempting to auto-select the paper size based on the document via the printInteractionController(_:choosePaper:) method in UIPrintInteractionControllerDelegate, using the bestPaperForPageSize(_:withPapersFromArray:) static method of UIPrintPaper. Again this selects a size that does not match the document, but it select the smallest size paper that will contain the pdf page (US Letter in this case). Again this was expected.
printInteractionController(_:choosePaper:) Code:
func printInteractionController(printInteractionController: UIPrintInteractionController, choosePaper paperList: [UIPrintPaper]) -> UIPrintPaper {
// Get the size of the PDF Page
let size: CGSize = pdf!.getPageSize()
// Let the Printer api pick the best UIPrintPaper object for the print job
let paper:UIPrintPaper = UIPrintPaper.bestPaperForPageSize(size, withPapersFromArray: paperList)
// Log: Paper Object, Paper Size, Paper's Printable Rectangle, Class type
print(size, paper, paper.paperSize, paper.printableRect, NSStringFromClass(paper.dynamicType))
// return UIPrintPaper object
return paper
}
print(size, paper, paper.paperSize, paper.printableRect, NSStringFromClass(paper.dynamicType)) output:
PDF Page Size: (792.0, 408.0)
Paper Object: <UIPrintPaper:0x7f8978fac450 <PKPaper: 0x7f8978fee460>>
Paper Size: (612.0, 792.0)
Paper Printable Rect: (11.9905511811024, 11.9905511811024, 588.018897637795, 768.018897637795)
Dynamic Object Type: UIPrintPaper
Attempt 3:
In this attempt I tried to get sneaky and subclass the UIPrintPaper object and then force bestPaperForPageSize(_:withPapersFromArray:) to return my desired paper size.
UIPrintPaper subclass:
import UIKit
class CaseCard: UIPrintPaper {
internal override var paperSize: CGSize {
get {
return CGSizeMake(5.66 * 72, 11 * 72)
}
}
internal override var printableRect: CGRect {
get {
return CGRectMake(0, 0, 5.66 * 72, 11 * 72)
}
}
}
printInteractionController(_:choosePaper:) Code:
func printInteractionController(printInteractionController: UIPrintInteractionController, choosePaper paperList: [UIPrintPaper]) -> UIPrintPaper {
// Force selection of custom paper size
let paper:UIPrintPaper = CaseCard() as UIPrintPaper
// Log: Paper Object, Paper Size, Paper's Printable Rectangle, Class type
print( paper, paper.paperSize, paper.printableRect, NSStringFromClass(paper.dynamicType))
// UIPrintPaper object
return paper
}
print(paper, paper.paperSize, paper.printableRect, NSStringFromClass(paper.dynamicType)) output:
Paper Object: <UIPrintPaper:0x7f9ebb5b6b30 (null)>
Paper Size: (407.52, 792.0)
Paper Printable Rect: (0.0, 0.0, 407.52, 792.0)
Dynamic Object Type : pdfviewer1.CaseCard
This is where things get interesting. You will notice that the Paper Object differs from Attempt 2 and Attempt 3.
Attempt 2 > Paper Object: <UIPrintPaper:0x7f8978fac450 <PKPaper: 0x7f8978fee460>>
Attempt 3 > Paper Object: <UIPrintPaper:0x7f9ebb5b6b30 (null)>
Attempt 2 returns a predefined UIPrintPaper object, which is backed by a PrintKit.PKPaper instance, which is a private framework object that is inaccessible to developers. Attempt 3 returns my subclass'd UIPrintPaper, but without he PrintKit.PKPaper instance. Unfortuantely there is no way to assign a PKPaper object during the instantiation of the custom UIPrintPaper and the UIPrintInteractionController fallbacks to it's default size of US Letter (8.5 x11)
So after all that, the question is: Can you print to a custom paper size from iOS UIPrintInteractionController?
As of right now, I don't think this is possible, but I would love to be proven wrong. Even if it was in a future release of iOS
(edit: typos, and there are probably still more)