I have develop functionality to print tags via iOS application. Till iOS 17 it's print properly but after updating to iOS 18 it scale more then 3x.
iOS 17 Name tag rect paperRect: (0.0, 0.0, 266.51338582677164, 175.748031496063) before adjustedPrintableRect: (8.588976377952747, 4.365354330708661, 249.33543307086615, 167.01732283464568)
iOS 18 Name tag rect paperRect: (0.0, 0.0, 841.8897637795276, 595.2755905511812) before adjustedPrintableRect: (39.99685039370081, 18.0, 783.8929133858268, 559.2755905511812)
class AirprintLabelRenderer: UIPrintPageRenderer {
private let imagesToRender: [UIImage]
init(imagesToRender: [UIImage]) {
self.imagesToRender = imagesToRender
super.init()
}
override var numberOfPages: Int {
return imagesToRender.count
}
override func drawPage(at pageIndex: Int, in printableRect: CGRect) {
print("printableRect: \(printableRect)")
imagesToRender[pageIndex].draw(in: printableRect)
}
}
class AirprintTagPrinter: NSObject, TagPrinter {
var identifier: String {
return printer.url.absoluteString
}
let displayName: String
let printerType = TagPrinterType.airprint
private let printer: UIPrinter
init(name: String, printer: UIPrinter) {
self.displayName = name
self.printer = printer
}
func toPrinter(jobs: [TagPrintJob], callBack: @escaping TagPrinter.TagPrinterPrintCallback) {
//Airprint has to be pushed to the main thread because of the way the labels are created (via nibs and UIImages)
DispatchQueue.main.async {
let printingItems = jobs.compactMap { self.buildItem(for: $0) }
guard printingItems.count > 0 else {
callBack(AirprintPrinterResult(successfulJobs: jobs, error: nil))
return
}
let controller = UIPrintInteractionController.shared
controller.showsNumberOfCopies = false
controller.printInfo = self.buildPrinterInfo()
controller.printPageRenderer = AirprintLabelRenderer(imagesToRender: printingItems)
controller.delegate = self
controller.print(to: self.printer) { (controller, completed, error) in
if let error = error {
Logger.error("An error occurred printing to airprinter: \(error)")
callBack(AirprintPrinterResult(successfulJobs: [], error: error))
} else {
callBack(AirprintPrinterResult(successfulJobs: jobs, error: error))
}
}
}
}
private func buildItem(for job: TagPrintJob) -> UIImage? {
var viewToTransform: UIView?
switch job {
case let testJob as TestTagPrintJob:
let testTag = TestTagAirPrintLabel.loadFromNib(named: "TestTagAirPrintLabel")
testTag?.setupUI(from: testJob)
viewToTransform = testTag
case let nameJob as NameTagPrintJob:
let nameTag = NameTagAirPrintLabel.loadFromNib(named: "NameTagAirPrintLabel")
nameTag?.setupUI(from: nameJob)
viewToTransform = nameTag
default:
viewToTransform = nil
}
return viewToTransform?.toImage(size: CGSize(width: 550, height: 420))
}
private func buildPrinterInfo() -> UIPrintInfo {
let printInfo = UIPrintInfo.printInfo()
printInfo.outputType = .photoGrayscale
printInfo.jobName = "AirPrint"
printInfo.orientation = .landscape
printInfo.duplex = .none
return printInfo
}
}
extension AirprintTagPrinter: UIPrintInteractionControllerDelegate {
func printInteractionController(_ printInteractionController: UIPrintInteractionController, chooseCutterBehavior availableBehaviors: [Any]) -> UIPrinter.CutterBehavior {
return .cutAfterEachJob
}
}
To solve this problem I have changed only one line. which is following.
From:
controller.printPageRenderer = AirprintLabelRenderer(imagesToRender: printingItems)
To:
controller.printingItems = printingItems