What I was trying to do is to print a file to a shared CUPS printer on the network without user to select from the UIPrinterPickerController or UIPrintInteractionController.
Using UIPrinterPickerController to select one from the list and then print works fine. But the problem is our network has way too many printers, and the user not always select the correct printer, so I need to set a printer from the app instead of letting user to select.
From Apple's dev document UIPrinter init(url:), I should be able to create a UIPrinter instance from a URL, and use contactPrinter(_:) to fetch all necessary fields of the printer.
Printer setup
The printer is connected and shared on a CUPS printer server, with static ip, and the printer shows, and prints fine from UIPrinterPickerController. And I logged url from UIPrinterPickerController
ipps://desktop.local.:631/printers/label_printer
Code I'm having issue
func testPrint(_ printingData: Data) {
guard let url = URL(string: printerURLString) else {
print("invalid url")
return
}
let printer = UIPrinter(url: url)
printer.contactPrinter { available in
print(available, "from contactPrinter") // This line prints false every time
}
UIPrintInteractionController.shared.printingItem = printingData
UIPrintInteractionController.shared.print(to: printer)
}
printerURLString I tried
- ipps://desktop.local.:631/printers/label_printer
- ipps://10.1.0.2:631/printers/label_printer
when I try to contactPrinter, the completionHandler always retrieved false, and of course it won't print anything.
Apple Code-Level Support
I tried to ask help from Apple, but they rejected the ticket without giving any reason nor any response. Not sure what's going on
Other thoughts
I have searched all related questions on stack overflow, but not really finding anything works, this post from a few years ago mentioned
Shared printers on Linux will not work with this contactPrinter method. It requires that the printer attributes are returned successfully. We often still send a print job even if the other parts fail.
For these methods to work properly, the server has to be a licensed and correctly implemented AirPrint server. CUPS running somewhere isn’t enough.
This doesn't make sense when UIPrinterPickerController can select the printer and print, but not create from the URL.
I tried to create a new printer instance from the UIPrinterPickerController, using the selected printer url, and that still won't work
picker.present(animated: true) { picker, _, _ in
if let printer = picker.selectedPrinter {
print(printer.url.absoluteString)
// selectedPrinter = picker.selectedPrinter
let newPrinter = UIPrinter(url: printer.url)
newPrinter.contactPrinter { success in
print("new printer:\(success)")
}
selectedPrinter = newPrinter
}
context.coordinator.activePicker = nil
self.showPrinterPicker = false
}