ios - how - Renderizar una UIView en un PDF como vectores en un iPad: a veces se representa como mapa de bits, a veces como vectores
webkit xcode 10 (5)
¿Qué pasa si agrega la vista en la pantalla pero en coordenadas fuera de pantalla? Esto parece más como un truco, pero podría funcionar.
Tengo una aplicación para iPad y estoy tratando de generar un PDF desde una UIView y casi funciona perfectamente.
El código es realmente simple de la siguiente manera:
UIGraphicsBeginPDFContextToFile( filename, bounds, nil );
UIGraphicsBeginPDFPage();
CGContextRef pdfContext = UIGraphicsGetCurrentContext();
[view.layer renderInContext:pdfContext];
UIGraphicsEndPDFContext();
Esto funciona muy bien con una excepción extraña. Si la vista ha estado en pantalla antes de ser procesada en PDF, los UILabels en la vista se renderizan en el PDF como maravillosos vectores. Si la vista aún no se ha visualizado en la pantalla (es decir, el controlador fue initWithNib, etc., pero no se ha insertado en un controlador de navegación ni nada), el texto se representa como un mapa de bits con resolución de ''ipad''.
Es como si el acto de obtener renderizado en la pantalla configura la vista para que se represente como vectores cuando posteriormente lo transfiero a un contexto pdf.
¿Hay algún método al que pueda llamar o una propiedad que pueda establecer en la vista o en la capa o en otro lugar para imitar este comportamiento sin tener que mostrar la vista en la pantalla?
¿Tiene algo que ver con UIViewPrintFormatter?
Intenta usar la vista viewPrintFormatter.
En lugar de [view.layer renderInContext:pdfContext];
prueba esto
CALayer* formattedLayer = [view viewPrintFormatter].view.layer;
[formattedLayer renderInContext:pdfContext];
La única forma que encontré para que las etiquetas se vuelvan vectorizadas es usar una subclase de UILabel con el siguiente método:
/** Overriding this CALayer delegate method is the magic that allows us to draw a vector version of the label into the layer instead of the default unscalable ugly bitmap */
- (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx {
BOOL isPDF = !CGRectIsEmpty(UIGraphicsGetPDFContextBounds());
if (!layer.shouldRasterize && isPDF)
[self drawRect:self.bounds]; // draw unrasterized
else
[super drawLayer:layer inContext:ctx];
}
Eso es lo que hace el truco para mí: las etiquetas no están seccionadas y se pueden seleccionar en la vista de PDF resultante, y se comportan normalmente cuando se procesan en la pantalla.
Quiero sugerir una alternativa a la gran solución de mprudhom: Usando las extensiones UIString
también puede hacer que el texto en el UILabel
se represente como fuente (con select''n''copy support etc.) De esta forma los glifos de la fuente se incrustan en el PDF correctamente
Para admitir las alineaciones de texto a la derecha y al centro, así como la alineación centrada vertical predeterminada, tuve que calcular un cuadro delimitador para el método drawInRect
.
- (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx
{
BOOL isPDF = !CGRectIsEmpty(UIGraphicsGetPDFContextBounds());
if (!layer.shouldRasterize && isPDF) {
// [self drawRect:self.bounds];
CGSize fitSize = [self sizeThatFits:self.bounds.size];
float x = self.bounds.origin.x;
float y = self.bounds.origin.y;
if (self.textAlignment == NSTextAlignmentCenter) {
x += (self.bounds.size.width - fitSize.width) / 2.0f;
y += (self.bounds.size.height - fitSize.height) / 2.0f;
} else if (self.textAlignment == NSTextAlignmentRight) {
x += self.bounds.size.width - fitSize.width;
y += self.bounds.size.height - fitSize.height;
}
[self.textColor set];
[self.text drawInRect:CGRectMake(x, y, fitSize.width, fitSize.height) withFont:self.font lineBreakMode:NSLineBreakByWordWrapping alignment:self.textAlignment];
} else {
[super drawLayer:layer inContext:ctx];
}
}
Use drawInContext
lugar de renderInContext
.