ios swift airprint

¿Cómo AirPrint varios formateadores de impresión de una sola vez?



swift (1)

Mi objetivo final es crear múltiples UIMarkupTextPrintFormatter e imprimirlos todos en un solo trabajo de impresión.

Por ejemplo, el primer formateador contiene texto que llena la primera página y un poco de la segunda página. Aunque todavía queda espacio para imprimir el segundo formateador, quiero que el segundo formateador se imprima en la tercera página. Entonces, básicamente, antes de imprimir otro formateador, comience una nueva página.

No puedo saber cuántas páginas se llenará un formateador en el momento de la compilación porque depende de la entrada del usuario. Tal vez 1, 2 o más.

Escuché que necesito usar UIPrintPageRenderer así que leí sus documentos y probé esto:

// I''m using webviews here because I don''t want to write 2 pages worth of markup... // it should be the same anyway. The two webviews display different wikipedia articles // Also, don''t judge my variable names. I''m lazy and this is just test code... let formatter = webView.viewPrintFormatter() let formatter1 = webView2.viewPrintFormatter() formatter.contentInsets = UIEdgeInsets(top: 72, left: 72, bottom: 72, right: 72) formatter1.contentInsets = UIEdgeInsets(top: 72, left: 72, bottom: 72, right: 72) let renderer = UIPrintPageRenderer() renderer.addPrintFormatter(formatter, startingAtPageAt: 0) renderer.addPrintFormatter(formatter1, startingAtPageAt: formatter.pageCount) printController.printPageRenderer = renderer printController.present(animated: true, completionHandler: nil)

Para agregar el segundo formateador de impresión, utilicé formatter.pageCount como segundo argumento. Esperaba que agregara el segundo formateador después de la última página de la primera. Pero no fue así. Sólo se imprimió el material en el segundo formateador.

Imprimí formatter.pageCount y encontré que su valor es 0.

Estoy totalmente confundido. ¿Cómo puedo obtener la cantidad de páginas que se llenará con un formateador?

También intenté implementar mi propio renderizador:

class MyRenderer: UIPrintPageRenderer { override func drawPrintFormatter(_ printFormatter: UIPrintFormatter, forPageAt pageIndex: Int) { printFormatter.draw(in: self.printableRect, forPageAt: pageIndex) } }

Pero luego simplemente se bloquea cuando el controlador de interacción de impresión muestra:

Se intentó obtener el bloqueo web de un subproceso que no sea el hilo principal o el hilo web. Esto puede ser el resultado de llamar a UIKit desde un hilo secundario. Chocando ahora ...

¿Qué hice mal en mi código?


Según el documento, parece que UIPrintFormatter necesita toda la información antes de calcular el número de páginas para imprimir en el formato.

UIPrintFormatter publica una interfaz que le permite especificar la página de inicio para un trabajo de impresión y los márgenes alrededor del contenido impreso; dada esa información más el contenido, un formateador de impresión calcula el número de páginas para el trabajo de impresión.

Por lo tanto, esto no sucederá a menos que UIPrintFormatter comience a imprimir el contenido.

Como UIPrintPageRenderer puede usar UIPrintFormatter , puede obtener la cantidad de páginas asociadas con el formateador y todo lo que tiene que hacer es anular numberOfPages para configurar un formateador diferente en cada página.

A continuación se muestra el código de ejemplo de Apple. Lo que hace exactamente lo mismo: adjuntar múltiples formateadores ( UIMarkupTextPrintFormatter ) en cada página.

Anula numberOfPages aquí:

- (NSInteger)numberOfPages { self.printFormatters = nil; [self setupPrintFormatters]; return [super numberOfPages]; }

Y adjuntar formateador a cada página aquí:

/* Iterate through the recipes setting each of their html representations into a UIMarkupTextPrintFormatter and add that formatter to the printing job. */ - (void)setupPrintFormatters { NSInteger page = 0; CGFloat previousFormatterMaxY = CGRectGetMinY(self.contentArea); for (Recipe *recipe in recipes) { NSString *html = recipe.htmlRepresentation; UIMarkupTextPrintFormatter *formatter = [[UIMarkupTextPrintFormatter alloc] initWithMarkupText:html]; [formatterToRecipeMap setObject:recipe forKey:formatter]; // Make room for the recipe info UIEdgeInsets contentInsets = UIEdgeInsetsZero; contentInsets.top = previousFormatterMaxY + self.recipeInfoHeight; if (contentInsets.top > CGRectGetMaxY(self.contentArea)) { // Move to the next page page++; contentInsets.top = CGRectGetMinY(self.contentArea) + self.recipeInfoHeight; } formatter.contentInsets = contentInsets; // Add the formatter to the renderer at the specified page [self addPrintFormatter:formatter startingAtPageAtIndex:page]; page = formatter.startPage + formatter.pageCount - 1; previousFormatterMaxY = CGRectGetMaxY([formatter rectForPageAtIndex:page]); } }

En resumen, está calculando el número de página según el área de contenido, la inserción de contenido y luego adjuntando el formateador a la página llamando a la API:

[self addPrintFormatter:formatter startingAtPageAtIndex:page];

De esta manera, Renderer tiene información sobre el formateador para cada página. Puedes encontrar el código completo here

Espero que ayude.