I'm trying to render a UIView to PDF, while maintaining text elements as actual text and not rasterizing them.
I'm using TextKit 2 backed UITextView and NSTextLayoutManager to provide the contents. However, no matter what I do, UITextView gets rasterized into a bitmap.
Here's the basic code:
let renderer = UIGraphicsPDFRenderer(bounds: pageRect, format: format)
let data = renderer.pdfData { (context) in
for page in self.pageViews {
context.beginPage()
let cgContext = context.cgContext
page.layer.render(in: cgContext)
}
}
A page view usually contains one UITextView, which uses somewhat advanced layout, so unfortunately I can't just toss it into a single NSAttributedString and draw into a CoreText context.
There's a hack to get UILabels to render themselves as non-rasterized text, and if I understand correctly, it works by just actually drawing them on the current context.
Interestingly, when providing UILabel view via NSTextAttachmentViewProvider to a text view using TextKit 2, the UILabels inside a text view won't get rasterized:
This hinted that the actual text fragments are the ones that get rasterized when drawing, not the whole view, and I was right. You can enumerate the text fragments and draw them directly on the context, which makes them remain as text rather than become a bitmap:
page.textView?.textLayoutManager?.enumerateTextLayoutFragments(from: location, options: [.ensuresLayout, .estimatesSize, .ensuresExtraLineFragment], using: { fragment in
let frame = fragment.layoutFragmentFrame
fragment.draw(at: frame.origin, in: cgContext)
return true
})
However, this causes other issues, because layout coordinates will be all over the place and not confined to the text view itself (and even more so for my custom NSTextLayoutFragment class), and text attachments won't get drawn this way either, but display a skewed placeholder icon.
I'm wondering if there is a way to make UITextView and NSTextLayoutManager to draw their contents similar to UILabel, so the fragments would remain as text in the PDF, rather than become a bitmap?

Here's a simple way to render a
UITextViewas real text into a PDF using TextKit 2. It currently supports only one text attachment per paragraph, because you apparently can't usefragment.draw(at:origin:)to draw attachments.I have no idea why Apple decided not to include this as default behavior in
UITextView, because it seems entirely possible.