Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
478 views
in Technique[技术] by (71.8m points)

ios - Rendering a UIView into a PDF as vectors on an iPad - Sometimes renders as bitmap, sometimes as vectors

I have an iPad app and I'm trying to generate a PDF from a UIView and it's almost working perfectly.

The code is really simple as follows:

UIGraphicsBeginPDFContextToFile( filename, bounds, nil );
UIGraphicsBeginPDFPage();
CGContextRef pdfContext = UIGraphicsGetCurrentContext();
[view.layer renderInContext:pdfContext];
UIGraphicsEndPDFContext();

This works really well with one weird exception. If the view has been on screen before being rendered to PDF then the UILabels on the view are rendered to the PDF as wonderful vectors. If the view has not yet been on the screen (IE the controller was initWithNib etc but hasn't been pushed into a navigation controller or anything) then the text is rendered as a bitmap at 'ipad' resolution.

It's like the act of getting rendered to the screen sets up the view to be rendered as vectors when I subsequently render it to a pdf context.

Is there some method I can call or property I can set on the view or the layer or elsewhere to mimic this behaviour without having to show the view on screen?

Is it something to do with UIViewPrintFormatter?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

The only way I found to make it so labels are rendered vectorized is to use a subclass of UILabel with the following method:

/** 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];
}

Swift 5.x:

override func draw(_ layer: CALayer, in ctx: CGContext) {
    let isPDF = !UIGraphicsGetPDFContextBounds().isEmpty

    if !self.layer.shouldRasterize && isPDF {
        self.draw(self.bounds)
    } else {
        super.draw(layer, in: ctx)
    }
}

That does the trick for me: labels are unrasterized and selectable in the resulting PDF view, and behave normally when rendered to the screen.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...