iOS Custom UIPrintPaper size

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)

Replies

Were you ever able to print to a custom paper size?

I'm having the same problem - and had tried the same steps already. Did you ever find a solution?

Surprisingly I followed the first steps the same way. Then I tried to override as you suggested in xcode 13.4. in 2022, still there is no way to avoid it falling back to Letter.

Even tried not giving any option or only giving other options in the bestPaper. Actually not just selecting , actually bestPaper seems like not working as expected even, only selecting something bigger. (as minimum is letter)

Just a note: The preview actually showing the size that you sent, just the selection is letter. Still doesnt resolve by experience.