Committed by
GitHub
fix: re-init UIPrinter cause issues with delegate (#1363)
* fix: re-init UIPrinter cause issues with delegate * change selectedPrinters to map of URL:UIPrinter
Showing
1 changed file
with
97 additions
and
75 deletions
| @@ -21,6 +21,10 @@ func dataProviderReleaseDataCallback(info _: UnsafeMutableRawPointer?, data: Uns | @@ -21,6 +21,10 @@ func dataProviderReleaseDataCallback(info _: UnsafeMutableRawPointer?, data: Uns | ||
| 21 | data.deallocate() | 21 | data.deallocate() |
| 22 | } | 22 | } |
| 23 | 23 | ||
| 24 | +// A variable that holds the selected printers to prevent recreate it if selected again | ||
| 25 | +// Each printer will be identified by its URL string | ||
| 26 | +var selectedPrinters = [String: UIPrinter]() | ||
| 27 | + | ||
| 24 | public class PrintJob: UIPrintPageRenderer, UIPrintInteractionControllerDelegate { | 28 | public class PrintJob: UIPrintPageRenderer, UIPrintInteractionControllerDelegate { |
| 25 | private var printing: PrintingPlugin | 29 | private var printing: PrintingPlugin |
| 26 | public var index: Int | 30 | public var index: Int |
| @@ -32,14 +36,14 @@ public class PrintJob: UIPrintPageRenderer, UIPrintInteractionControllerDelegate | @@ -32,14 +36,14 @@ public class PrintJob: UIPrintPageRenderer, UIPrintInteractionControllerDelegate | ||
| 32 | private let semaphore = DispatchSemaphore(value: 0) | 36 | private let semaphore = DispatchSemaphore(value: 0) |
| 33 | private var dynamic = false | 37 | private var dynamic = false |
| 34 | private var currentSize: CGSize? | 38 | private var currentSize: CGSize? |
| 35 | - | 39 | + |
| 36 | public init(printing: PrintingPlugin, index: Int) { | 40 | public init(printing: PrintingPlugin, index: Int) { |
| 37 | self.printing = printing | 41 | self.printing = printing |
| 38 | self.index = index | 42 | self.index = index |
| 39 | pdfDocument = nil | 43 | pdfDocument = nil |
| 40 | super.init() | 44 | super.init() |
| 41 | } | 45 | } |
| 42 | - | 46 | + |
| 43 | override public func drawPage(at pageIndex: Int, in _: CGRect) { | 47 | override public func drawPage(at pageIndex: Int, in _: CGRect) { |
| 44 | let ctx = UIGraphicsGetCurrentContext() | 48 | let ctx = UIGraphicsGetCurrentContext() |
| 45 | let page = pdfDocument?.page(at: pageIndex + 1) | 49 | let page = pdfDocument?.page(at: pageIndex + 1) |
| @@ -49,7 +53,7 @@ public class PrintJob: UIPrintPageRenderer, UIPrintInteractionControllerDelegate | @@ -49,7 +53,7 @@ public class PrintJob: UIPrintPageRenderer, UIPrintInteractionControllerDelegate | ||
| 49 | ctx?.drawPDFPage(page!) | 53 | ctx?.drawPDFPage(page!) |
| 50 | } | 54 | } |
| 51 | } | 55 | } |
| 52 | - | 56 | + |
| 53 | func cancelJob(_ error: String?) { | 57 | func cancelJob(_ error: String?) { |
| 54 | pdfDocument = nil | 58 | pdfDocument = nil |
| 55 | if dynamic { | 59 | if dynamic { |
| @@ -58,23 +62,23 @@ public class PrintJob: UIPrintPageRenderer, UIPrintInteractionControllerDelegate | @@ -58,23 +62,23 @@ public class PrintJob: UIPrintPageRenderer, UIPrintInteractionControllerDelegate | ||
| 58 | printing.onCompleted(printJob: self, completed: false, error: error as NSString?) | 62 | printing.onCompleted(printJob: self, completed: false, error: error as NSString?) |
| 59 | } | 63 | } |
| 60 | } | 64 | } |
| 61 | - | 65 | + |
| 62 | func setDocument(_ data: Data?) { | 66 | func setDocument(_ data: Data?) { |
| 63 | let bytesPointer = UnsafeMutablePointer<UInt8>.allocate(capacity: data?.count ?? 0) | 67 | let bytesPointer = UnsafeMutablePointer<UInt8>.allocate(capacity: data?.count ?? 0) |
| 64 | data?.copyBytes(to: bytesPointer, count: data?.count ?? 0) | 68 | data?.copyBytes(to: bytesPointer, count: data?.count ?? 0) |
| 65 | let dataProvider = CGDataProvider(dataInfo: nil, data: bytesPointer, size: data?.count ?? 0, releaseData: dataProviderReleaseDataCallback) | 69 | let dataProvider = CGDataProvider(dataInfo: nil, data: bytesPointer, size: data?.count ?? 0, releaseData: dataProviderReleaseDataCallback) |
| 66 | pdfDocument = CGPDFDocument(dataProvider!) | 70 | pdfDocument = CGPDFDocument(dataProvider!) |
| 67 | - | 71 | + |
| 68 | if dynamic { | 72 | if dynamic { |
| 69 | // Unblock the main thread | 73 | // Unblock the main thread |
| 70 | semaphore.signal() | 74 | semaphore.signal() |
| 71 | return | 75 | return |
| 72 | } | 76 | } |
| 73 | - | 77 | + |
| 74 | DispatchQueue.main.async { [self] in | 78 | DispatchQueue.main.async { [self] in |
| 75 | let controller = UIPrintInteractionController.shared | 79 | let controller = UIPrintInteractionController.shared |
| 76 | controller.delegate = self | 80 | controller.delegate = self |
| 77 | - | 81 | + |
| 78 | let printInfo = UIPrintInfo.printInfo() | 82 | let printInfo = UIPrintInfo.printInfo() |
| 79 | printInfo.jobName = jobName! | 83 | printInfo.jobName = jobName! |
| 80 | printInfo.outputType = .general | 84 | printInfo.outputType = .general |
| @@ -84,30 +88,35 @@ public class PrintJob: UIPrintPageRenderer, UIPrintInteractionControllerDelegate | @@ -84,30 +88,35 @@ public class PrintJob: UIPrintPageRenderer, UIPrintInteractionControllerDelegate | ||
| 84 | } | 88 | } |
| 85 | controller.printInfo = printInfo | 89 | controller.printInfo = printInfo |
| 86 | controller.printPageRenderer = self | 90 | controller.printPageRenderer = self |
| 87 | - | 91 | + |
| 88 | if self.printerName != nil { | 92 | if self.printerName != nil { |
| 89 | let printerURL = URL(string: self.printerName!) | 93 | let printerURL = URL(string: self.printerName!) |
| 90 | - | 94 | + |
| 91 | if printerURL == nil { | 95 | if printerURL == nil { |
| 92 | self.printing.onCompleted(printJob: self, completed: false, error: "Unable to find printer URL") | 96 | self.printing.onCompleted(printJob: self, completed: false, error: "Unable to find printer URL") |
| 93 | return | 97 | return |
| 94 | } | 98 | } |
| 95 | - | ||
| 96 | - let printer = UIPrinter(url: printerURL!) | ||
| 97 | - printer.contactPrinter { available in | 99 | + |
| 100 | + let printerURLString = printerURL!.absoluteString | ||
| 101 | + | ||
| 102 | + if !selectedPrinters.keys.contains(printerURLString) { | ||
| 103 | + selectedPrinters[printerURLString] = UIPrinter(url: printerURL!) | ||
| 104 | + } | ||
| 105 | + | ||
| 106 | + selectedPrinters[printerURLString]!.contactPrinter { available in | ||
| 98 | if !available { | 107 | if !available { |
| 99 | self.printing.onCompleted(printJob: self, completed: false, error: "Printer not available") | 108 | self.printing.onCompleted(printJob: self, completed: false, error: "Printer not available") |
| 100 | return | 109 | return |
| 101 | } | 110 | } |
| 102 | - | ||
| 103 | - controller.print(to: printer, completionHandler: self.completionHandler) | 111 | + |
| 112 | + controller.print(to: selectedPrinters[printerURLString]!, completionHandler: self.completionHandler) | ||
| 104 | } | 113 | } |
| 105 | } else { | 114 | } else { |
| 106 | controller.present(animated: true, completionHandler: self.completionHandler) | 115 | controller.present(animated: true, completionHandler: self.completionHandler) |
| 107 | } | 116 | } |
| 108 | } | 117 | } |
| 109 | } | 118 | } |
| 110 | - | 119 | + |
| 111 | override public var numberOfPages: Int { | 120 | override public var numberOfPages: Int { |
| 112 | if dynamic { | 121 | if dynamic { |
| 113 | printing.onLayout( | 122 | printing.onLayout( |
| @@ -119,19 +128,19 @@ public class PrintJob: UIPrintPageRenderer, UIPrintInteractionControllerDelegate | @@ -119,19 +128,19 @@ public class PrintJob: UIPrintPageRenderer, UIPrintInteractionControllerDelegate | ||
| 119 | marginRight: paperRect.size.width - (printableRect.origin.x + printableRect.size.width), | 128 | marginRight: paperRect.size.width - (printableRect.origin.x + printableRect.size.width), |
| 120 | marginBottom: paperRect.size.height - (printableRect.origin.y + printableRect.size.height) | 129 | marginBottom: paperRect.size.height - (printableRect.origin.y + printableRect.size.height) |
| 121 | ) | 130 | ) |
| 122 | - | 131 | + |
| 123 | // Block the main thread, waiting for a document | 132 | // Block the main thread, waiting for a document |
| 124 | semaphore.wait() | 133 | semaphore.wait() |
| 125 | } | 134 | } |
| 126 | - | 135 | + |
| 127 | return pdfDocument?.numberOfPages ?? 0 | 136 | return pdfDocument?.numberOfPages ?? 0 |
| 128 | } | 137 | } |
| 129 | - | 138 | + |
| 130 | func completionHandler(printController _: UIPrintInteractionController, completed: Bool, error: Error?) { | 139 | func completionHandler(printController _: UIPrintInteractionController, completed: Bool, error: Error?) { |
| 131 | if !completed, error != nil { | 140 | if !completed, error != nil { |
| 132 | print("Unable to print: \(error?.localizedDescription ?? "unknown error")") | 141 | print("Unable to print: \(error?.localizedDescription ?? "unknown error")") |
| 133 | } | 142 | } |
| 134 | - | 143 | + |
| 135 | printing.onCompleted(printJob: self, completed: completed, error: error?.localizedDescription as NSString?) | 144 | printing.onCompleted(printJob: self, completed: completed, error: error?.localizedDescription as NSString?) |
| 136 | } | 145 | } |
| 137 | 146 | ||
| @@ -144,7 +153,7 @@ public class PrintJob: UIPrintPageRenderer, UIPrintInteractionControllerDelegate | @@ -144,7 +153,7 @@ public class PrintJob: UIPrintPageRenderer, UIPrintInteractionControllerDelegate | ||
| 144 | 153 | ||
| 145 | return bestPaper | 154 | return bestPaper |
| 146 | } | 155 | } |
| 147 | - | 156 | + |
| 148 | func printPdf(name: String, withPageSize size: CGSize, andMargin margin: CGRect, withPrinter printerID: String?, dynamically dyn: Bool) { | 157 | func printPdf(name: String, withPageSize size: CGSize, andMargin margin: CGRect, withPrinter printerID: String?, dynamically dyn: Bool) { |
| 149 | currentSize = size | 158 | currentSize = size |
| 150 | dynamic = dyn | 159 | dynamic = dyn |
| @@ -153,17 +162,17 @@ public class PrintJob: UIPrintPageRenderer, UIPrintInteractionControllerDelegate | @@ -153,17 +162,17 @@ public class PrintJob: UIPrintPageRenderer, UIPrintInteractionControllerDelegate | ||
| 153 | self.printing.onCompleted(printJob: self, completed: false, error: "Printing not available") | 162 | self.printing.onCompleted(printJob: self, completed: false, error: "Printing not available") |
| 154 | return | 163 | return |
| 155 | } | 164 | } |
| 156 | - | 165 | + |
| 157 | if size.width > size.height { | 166 | if size.width > size.height { |
| 158 | orientation = UIPrintInfo.Orientation.landscape | 167 | orientation = UIPrintInfo.Orientation.landscape |
| 159 | } | 168 | } |
| 160 | - | 169 | + |
| 161 | jobName = name | 170 | jobName = name |
| 162 | printerName = printerID | 171 | printerName = printerID |
| 163 | - | 172 | + |
| 164 | let controller = UIPrintInteractionController.shared | 173 | let controller = UIPrintInteractionController.shared |
| 165 | controller.delegate = self | 174 | controller.delegate = self |
| 166 | - | 175 | + |
| 167 | let printInfo = UIPrintInfo.printInfo() | 176 | let printInfo = UIPrintInfo.printInfo() |
| 168 | printInfo.jobName = jobName! | 177 | printInfo.jobName = jobName! |
| 169 | printInfo.outputType = .general | 178 | printInfo.outputType = .general |
| @@ -173,27 +182,40 @@ public class PrintJob: UIPrintPageRenderer, UIPrintInteractionControllerDelegate | @@ -173,27 +182,40 @@ public class PrintJob: UIPrintPageRenderer, UIPrintInteractionControllerDelegate | ||
| 173 | } | 182 | } |
| 174 | controller.printInfo = printInfo | 183 | controller.printInfo = printInfo |
| 175 | controller.showsPaperSelectionForLoadedPapers = true | 184 | controller.showsPaperSelectionForLoadedPapers = true |
| 176 | - | 185 | + |
| 177 | controller.printPageRenderer = self | 186 | controller.printPageRenderer = self |
| 178 | - | 187 | + |
| 179 | if printerID != nil { | 188 | if printerID != nil { |
| 180 | let printerURL = URL(string: printerID!) | 189 | let printerURL = URL(string: printerID!) |
| 181 | - | 190 | + |
| 182 | if printerURL == nil { | 191 | if printerURL == nil { |
| 183 | self.printing.onCompleted(printJob: self, completed: false, error: "Unable to find printer URL") | 192 | self.printing.onCompleted(printJob: self, completed: false, error: "Unable to find printer URL") |
| 184 | return | 193 | return |
| 185 | } | 194 | } |
| 186 | - | ||
| 187 | - let printer = UIPrinter(url: printerURL!) | ||
| 188 | - controller.print(to: printer, completionHandler: completionHandler) | 195 | + |
| 196 | + let printerURLString = printerURL!.absoluteString | ||
| 197 | + | ||
| 198 | + if !selectedPrinters.keys.contains(printerURLString) { | ||
| 199 | + selectedPrinters[printerURLString] = UIPrinter(url: printerURL!) | ||
| 200 | + } | ||
| 201 | + | ||
| 202 | + | ||
| 203 | + selectedPrinters[printerURLString]!.contactPrinter { available in | ||
| 204 | + if !available { | ||
| 205 | + self.printing.onCompleted(printJob: self, completed: false, error: "Printer not available") | ||
| 206 | + return | ||
| 207 | + } | ||
| 208 | + | ||
| 209 | + controller.print(to: selectedPrinters[printerURLString]!, completionHandler: self.completionHandler) | ||
| 210 | + } | ||
| 189 | return | 211 | return |
| 190 | } | 212 | } |
| 191 | - | 213 | + |
| 192 | if dynamic { | 214 | if dynamic { |
| 193 | controller.present(animated: true, completionHandler: completionHandler) | 215 | controller.present(animated: true, completionHandler: completionHandler) |
| 194 | return | 216 | return |
| 195 | } | 217 | } |
| 196 | - | 218 | + |
| 197 | self.printing.onLayout( | 219 | self.printing.onLayout( |
| 198 | printJob: self, | 220 | printJob: self, |
| 199 | width: size.width, | 221 | width: size.width, |
| @@ -204,18 +226,18 @@ public class PrintJob: UIPrintPageRenderer, UIPrintInteractionControllerDelegate | @@ -204,18 +226,18 @@ public class PrintJob: UIPrintPageRenderer, UIPrintInteractionControllerDelegate | ||
| 204 | marginBottom: size.height - margin.maxY | 226 | marginBottom: size.height - margin.maxY |
| 205 | ) | 227 | ) |
| 206 | } | 228 | } |
| 207 | - | 229 | + |
| 208 | static func sharePdf(data: Data, withSourceRect rect: CGRect, andName name: String, subject: String?, body: String?) { | 230 | static func sharePdf(data: Data, withSourceRect rect: CGRect, andName name: String, subject: String?, body: String?) { |
| 209 | let tmpDirURL = URL(fileURLWithPath: NSTemporaryDirectory(), isDirectory: true) | 231 | let tmpDirURL = URL(fileURLWithPath: NSTemporaryDirectory(), isDirectory: true) |
| 210 | let fileURL = tmpDirURL.appendingPathComponent(name) | 232 | let fileURL = tmpDirURL.appendingPathComponent(name) |
| 211 | - | 233 | + |
| 212 | do { | 234 | do { |
| 213 | try data.write(to: fileURL, options: .atomic) | 235 | try data.write(to: fileURL, options: .atomic) |
| 214 | } catch { | 236 | } catch { |
| 215 | print("sharePdf error: \(error.localizedDescription)") | 237 | print("sharePdf error: \(error.localizedDescription)") |
| 216 | return | 238 | return |
| 217 | } | 239 | } |
| 218 | - | 240 | + |
| 219 | let activityViewController = UIActivityViewController(activityItems: [fileURL, body as Any], applicationActivities: nil) | 241 | let activityViewController = UIActivityViewController(activityItems: [fileURL, body as Any], applicationActivities: nil) |
| 220 | activityViewController.setValue(subject, forKey: "subject") | 242 | activityViewController.setValue(subject, forKey: "subject") |
| 221 | if UIDevice.current.userInterfaceIdiom == .pad { | 243 | if UIDevice.current.userInterfaceIdiom == .pad { |
| @@ -225,7 +247,7 @@ public class PrintJob: UIPrintPageRenderer, UIPrintInteractionControllerDelegate | @@ -225,7 +247,7 @@ public class PrintJob: UIPrintPageRenderer, UIPrintInteractionControllerDelegate | ||
| 225 | } | 247 | } |
| 226 | UIApplication.shared.keyWindow?.rootViewController?.present(activityViewController, animated: true) | 248 | UIApplication.shared.keyWindow?.rootViewController?.present(activityViewController, animated: true) |
| 227 | } | 249 | } |
| 228 | - | 250 | + |
| 229 | func convertHtml(_ data: String, withPageSize rect: CGRect, andMargin margin: CGRect, andBaseUrl baseUrl: URL?) { | 251 | func convertHtml(_ data: String, withPageSize rect: CGRect, andMargin margin: CGRect, andBaseUrl baseUrl: URL?) { |
| 230 | let viewController = UIApplication.shared.delegate?.window?!.rootViewController | 252 | let viewController = UIApplication.shared.delegate?.window?!.rootViewController |
| 231 | let wkWebView = WKWebView(frame: viewController!.view.bounds) | 253 | let wkWebView = WKWebView(frame: viewController!.view.bounds) |
| @@ -233,32 +255,32 @@ public class PrintJob: UIPrintPageRenderer, UIPrintInteractionControllerDelegate | @@ -233,32 +255,32 @@ public class PrintJob: UIPrintPageRenderer, UIPrintInteractionControllerDelegate | ||
| 233 | wkWebView.tag = 100 | 255 | wkWebView.tag = 100 |
| 234 | viewController?.view.addSubview(wkWebView) | 256 | viewController?.view.addSubview(wkWebView) |
| 235 | wkWebView.loadHTMLString(data, baseURL: baseUrl ?? Bundle.main.bundleURL) | 257 | wkWebView.loadHTMLString(data, baseURL: baseUrl ?? Bundle.main.bundleURL) |
| 236 | - | 258 | + |
| 237 | urlObservation = wkWebView.observe(\.isLoading, changeHandler: { _, _ in | 259 | urlObservation = wkWebView.observe(\.isLoading, changeHandler: { _, _ in |
| 238 | // this is workaround for issue with loading local images | 260 | // this is workaround for issue with loading local images |
| 239 | DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) { | 261 | DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) { |
| 240 | // assign the print formatter to the print page renderer | 262 | // assign the print formatter to the print page renderer |
| 241 | let renderer = UIPrintPageRenderer() | 263 | let renderer = UIPrintPageRenderer() |
| 242 | renderer.addPrintFormatter(wkWebView.viewPrintFormatter(), startingAtPageAt: 0) | 264 | renderer.addPrintFormatter(wkWebView.viewPrintFormatter(), startingAtPageAt: 0) |
| 243 | - | 265 | + |
| 244 | // assign paperRect and printableRect values | 266 | // assign paperRect and printableRect values |
| 245 | renderer.setValue(rect, forKey: "paperRect") | 267 | renderer.setValue(rect, forKey: "paperRect") |
| 246 | renderer.setValue(margin, forKey: "printableRect") | 268 | renderer.setValue(margin, forKey: "printableRect") |
| 247 | - | 269 | + |
| 248 | // create pdf context and draw each page | 270 | // create pdf context and draw each page |
| 249 | let pdfData = NSMutableData() | 271 | let pdfData = NSMutableData() |
| 250 | UIGraphicsBeginPDFContextToData(pdfData, rect, nil) | 272 | UIGraphicsBeginPDFContextToData(pdfData, rect, nil) |
| 251 | - | 273 | + |
| 252 | for i in 0 ..< renderer.numberOfPages { | 274 | for i in 0 ..< renderer.numberOfPages { |
| 253 | UIGraphicsBeginPDFPage() | 275 | UIGraphicsBeginPDFPage() |
| 254 | renderer.drawPage(at: i, in: UIGraphicsGetPDFContextBounds()) | 276 | renderer.drawPage(at: i, in: UIGraphicsGetPDFContextBounds()) |
| 255 | } | 277 | } |
| 256 | - | 278 | + |
| 257 | UIGraphicsEndPDFContext() | 279 | UIGraphicsEndPDFContext() |
| 258 | - | 280 | + |
| 259 | if let viewWithTag = viewController?.view.viewWithTag(wkWebView.tag) { | 281 | if let viewWithTag = viewController?.view.viewWithTag(wkWebView.tag) { |
| 260 | viewWithTag.removeFromSuperview() // remove hidden webview when pdf is generated | 282 | viewWithTag.removeFromSuperview() // remove hidden webview when pdf is generated |
| 261 | - | 283 | + |
| 262 | // clear WKWebView cache | 284 | // clear WKWebView cache |
| 263 | if #available(iOS 9.0, *) { | 285 | if #available(iOS 9.0, *) { |
| 264 | WKWebsiteDataStore.default().fetchDataRecords(ofTypes: WKWebsiteDataStore.allWebsiteDataTypes()) { records in | 286 | WKWebsiteDataStore.default().fetchDataRecords(ofTypes: WKWebsiteDataStore.allWebsiteDataTypes()) { records in |
| @@ -268,40 +290,40 @@ public class PrintJob: UIPrintPageRenderer, UIPrintInteractionControllerDelegate | @@ -268,40 +290,40 @@ public class PrintJob: UIPrintPageRenderer, UIPrintInteractionControllerDelegate | ||
| 268 | } | 290 | } |
| 269 | } | 291 | } |
| 270 | } | 292 | } |
| 271 | - | 293 | + |
| 272 | // dispose urlObservation | 294 | // dispose urlObservation |
| 273 | self.urlObservation = nil | 295 | self.urlObservation = nil |
| 274 | self.printing.onHtmlRendered(printJob: self, pdfData: pdfData as Data) | 296 | self.printing.onHtmlRendered(printJob: self, pdfData: pdfData as Data) |
| 275 | } | 297 | } |
| 276 | }) | 298 | }) |
| 277 | } | 299 | } |
| 278 | - | 300 | + |
| 279 | static func pickPrinter(result: @escaping FlutterResult, withSourceRect rect: CGRect) { | 301 | static func pickPrinter(result: @escaping FlutterResult, withSourceRect rect: CGRect) { |
| 280 | let controller = UIPrinterPickerController(initiallySelectedPrinter: nil) | 302 | let controller = UIPrinterPickerController(initiallySelectedPrinter: nil) |
| 281 | - | 303 | + |
| 282 | let pickPrinterCompletionHandler: UIPrinterPickerController.CompletionHandler = { | 304 | let pickPrinterCompletionHandler: UIPrinterPickerController.CompletionHandler = { |
| 283 | (printerPickerController: UIPrinterPickerController, completed: Bool, error: Error?) in | 305 | (printerPickerController: UIPrinterPickerController, completed: Bool, error: Error?) in |
| 284 | - if !completed, error != nil { | ||
| 285 | - print("Unable to pick printer: \(error?.localizedDescription ?? "unknown error")") | ||
| 286 | - result(nil) | ||
| 287 | - return | ||
| 288 | - } | ||
| 289 | - | ||
| 290 | - if printerPickerController.selectedPrinter == nil { | ||
| 291 | - result(nil) | ||
| 292 | - return | ||
| 293 | - } | ||
| 294 | - | ||
| 295 | - let printer = printerPickerController.selectedPrinter! | ||
| 296 | - let data: NSDictionary = [ | ||
| 297 | - "url": printer.url.absoluteString as Any, | ||
| 298 | - "name": printer.displayName as Any, | ||
| 299 | - "model": printer.makeAndModel as Any, | ||
| 300 | - "location": printer.displayLocation as Any, | ||
| 301 | - ] | ||
| 302 | - result(data) | 306 | + if !completed, error != nil { |
| 307 | + print("Unable to pick printer: \(error?.localizedDescription ?? "unknown error")") | ||
| 308 | + result(nil) | ||
| 309 | + return | ||
| 310 | + } | ||
| 311 | + | ||
| 312 | + if printerPickerController.selectedPrinter == nil { | ||
| 313 | + result(nil) | ||
| 314 | + return | ||
| 315 | + } | ||
| 316 | + | ||
| 317 | + let printer = printerPickerController.selectedPrinter! | ||
| 318 | + let data: NSDictionary = [ | ||
| 319 | + "url": printer.url.absoluteString as Any, | ||
| 320 | + "name": printer.displayName as Any, | ||
| 321 | + "model": printer.makeAndModel as Any, | ||
| 322 | + "location": printer.displayLocation as Any, | ||
| 323 | + ] | ||
| 324 | + result(data) | ||
| 303 | } | 325 | } |
| 304 | - | 326 | + |
| 305 | if UIDevice.current.userInterfaceIdiom == .pad { | 327 | if UIDevice.current.userInterfaceIdiom == .pad { |
| 306 | let viewController: UIViewController? = UIApplication.shared.keyWindow?.rootViewController | 328 | let viewController: UIViewController? = UIApplication.shared.keyWindow?.rootViewController |
| 307 | if viewController != nil { | 329 | if viewController != nil { |
| @@ -309,10 +331,10 @@ public class PrintJob: UIPrintPageRenderer, UIPrintInteractionControllerDelegate | @@ -309,10 +331,10 @@ public class PrintJob: UIPrintPageRenderer, UIPrintInteractionControllerDelegate | ||
| 309 | return | 331 | return |
| 310 | } | 332 | } |
| 311 | } | 333 | } |
| 312 | - | 334 | + |
| 313 | controller.present(animated: true, completionHandler: pickPrinterCompletionHandler) | 335 | controller.present(animated: true, completionHandler: pickPrinterCompletionHandler) |
| 314 | } | 336 | } |
| 315 | - | 337 | + |
| 316 | public func rasterPdf(data: Data, pages: [Int]?, scale: CGFloat) { | 338 | public func rasterPdf(data: Data, pages: [Int]?, scale: CGFloat) { |
| 317 | guard | 339 | guard |
| 318 | let provider = CGDataProvider(data: data as CFData), | 340 | let provider = CGDataProvider(data: data as CFData), |
| @@ -321,10 +343,10 @@ public class PrintJob: UIPrintPageRenderer, UIPrintInteractionControllerDelegate | @@ -321,10 +343,10 @@ public class PrintJob: UIPrintPageRenderer, UIPrintInteractionControllerDelegate | ||
| 321 | printing.onPageRasterEnd(printJob: self, error: "Cannot raster a malformed PDF file") | 343 | printing.onPageRasterEnd(printJob: self, error: "Cannot raster a malformed PDF file") |
| 322 | return | 344 | return |
| 323 | } | 345 | } |
| 324 | - | 346 | + |
| 325 | DispatchQueue.global().async { | 347 | DispatchQueue.global().async { |
| 326 | let pageCount = document.numberOfPages | 348 | let pageCount = document.numberOfPages |
| 327 | - | 349 | + |
| 328 | for pageNum in pages ?? Array(0 ... pageCount - 1) { | 350 | for pageNum in pages ?? Array(0 ... pageCount - 1) { |
| 329 | guard let page = document.page(at: pageNum + 1) else { continue } | 351 | guard let page = document.page(at: pageNum + 1) else { continue } |
| 330 | let angle = CGFloat(page.rotationAngle) * CGFloat.pi / -180 | 352 | let angle = CGFloat(page.rotationAngle) * CGFloat.pi / -180 |
| @@ -333,7 +355,7 @@ public class PrintJob: UIPrintPageRenderer, UIPrintInteractionControllerDelegate | @@ -333,7 +355,7 @@ public class PrintJob: UIPrintPageRenderer, UIPrintInteractionControllerDelegate | ||
| 333 | let height = Int(abs((cos(angle) * rect.height + sin(angle) * rect.width) * scale)) | 355 | let height = Int(abs((cos(angle) * rect.height + sin(angle) * rect.width) * scale)) |
| 334 | let stride = width * 4 | 356 | let stride = width * 4 |
| 335 | var data = Data(repeating: 0, count: stride * height) | 357 | var data = Data(repeating: 0, count: stride * height) |
| 336 | - | 358 | + |
| 337 | data.withUnsafeMutableBytes { (outputBytes: UnsafeMutableRawBufferPointer) in | 359 | data.withUnsafeMutableBytes { (outputBytes: UnsafeMutableRawBufferPointer) in |
| 338 | let rgb = CGColorSpaceCreateDeviceRGB() | 360 | let rgb = CGColorSpaceCreateDeviceRGB() |
| 339 | let context = CGContext( | 361 | let context = CGContext( |
| @@ -345,7 +367,7 @@ public class PrintJob: UIPrintPageRenderer, UIPrintInteractionControllerDelegate | @@ -345,7 +367,7 @@ public class PrintJob: UIPrintPageRenderer, UIPrintInteractionControllerDelegate | ||
| 345 | space: rgb, | 367 | space: rgb, |
| 346 | bitmapInfo: CGImageAlphaInfo.premultipliedLast.rawValue | 368 | bitmapInfo: CGImageAlphaInfo.premultipliedLast.rawValue |
| 347 | ) | 369 | ) |
| 348 | - | 370 | + |
| 349 | if context != nil { | 371 | if context != nil { |
| 350 | context!.translateBy(x: CGFloat(width) / 2, y: CGFloat(height) / 2) | 372 | context!.translateBy(x: CGFloat(width) / 2, y: CGFloat(height) / 2) |
| 351 | context!.scaleBy(x: scale, y: scale) | 373 | context!.scaleBy(x: scale, y: scale) |
| @@ -354,18 +376,18 @@ public class PrintJob: UIPrintPageRenderer, UIPrintInteractionControllerDelegate | @@ -354,18 +376,18 @@ public class PrintJob: UIPrintPageRenderer, UIPrintInteractionControllerDelegate | ||
| 354 | context!.drawPDFPage(page) | 376 | context!.drawPDFPage(page) |
| 355 | } | 377 | } |
| 356 | } | 378 | } |
| 357 | - | 379 | + |
| 358 | DispatchQueue.main.sync { | 380 | DispatchQueue.main.sync { |
| 359 | self.printing.onPageRasterized(printJob: self, imageData: data, width: width, height: height) | 381 | self.printing.onPageRasterized(printJob: self, imageData: data, width: width, height: height) |
| 360 | } | 382 | } |
| 361 | } | 383 | } |
| 362 | - | 384 | + |
| 363 | DispatchQueue.main.sync { | 385 | DispatchQueue.main.sync { |
| 364 | self.printing.onPageRasterEnd(printJob: self, error: nil) | 386 | self.printing.onPageRasterEnd(printJob: self, error: nil) |
| 365 | } | 387 | } |
| 366 | } | 388 | } |
| 367 | } | 389 | } |
| 368 | - | 390 | + |
| 369 | public static func printingInfo() -> NSDictionary { | 391 | public static func printingInfo() -> NSDictionary { |
| 370 | let data: NSDictionary = [ | 392 | let data: NSDictionary = [ |
| 371 | "directPrint": true, | 393 | "directPrint": true, |
-
Please register or login to post a comment