Seeing you're producing any UI view or controllers meant for the main thread, you can run code in a background thread and just pass ima back to the main thread or write it a local disk.
import UIKit
import PDFKit
func extractImage(completion: @escaping ((UIImage)->Void)) {
guard let path = Bundle.main.path(forResource: "filename", ofType: "pdf") else { return }
let url = URL(fileURLWithPath: path)
// Instantiate a `CGPDFDocument` from the PDF file's URL.
guard let document = PDFDocument(url: url) else { return }
// Get the first page of the PDF document.
guard let page = document.page(at: 0) else { return }
// Fetch the page rect for the page we want to render.
let pageRect = page.bounds(for: .mediaBox)
let renderer = UIGraphicsImageRenderer(size: pageRect.size)
let img = renderer.image { ctx in
// Set and fill the background color.
UIColor.white.set()
ctx.fill(CGRect(x: 0, y: 0, width: pageRect.width, height: pageRect.height))
// Translate the context so that we only draw the `cropRect`.
ctx.cgContext.translateBy(x: -pageRect.origin.x, y: pageRect.size.height - pageRect.origin.y)
// Flip the context vertically because the Core Graphics coordinate system starts from the bottom.
ctx.cgContext.scaleBy(x: 1.0, y: -1.0)
// Draw the PDF page.
page.draw(with: .mediaBox, to: ctx.cgContext)
}
DispatchQueue.main.async {
completion(img)
}
}
DispatchQueue.global().async {
// call extract on a global Q
extractImage { image in
// Return UIImage on main thread
}
}