SwiftUI · · 4 min read

SwiftUI ImageRenderer: How to Create PDF Documents

SwiftUI ImageRenderer: How to Create PDF Documents

Earlier, we showed you how to use ImageRenderer to capture a SwiftUI view and save it as an image. This new class, introduced in iOS 16, can also let you convert a view into a PDF document.

In this tutorial, we will build on the top of the previous demo and add the Save to PDF function. To follow this tutorial, please use Xcode 14 beta 3 (or up).

Revisit the Demo App

If you haven’t read the previous tutorial, I suggest you to check it out first. It already covered the basics of ImageRenderer and explained the implementation of the demo app.


I have made some modifications to the demo app by adding a heading and a caption for the line chart. The demo app now also comes with a PDF button for saving the chart view in a PDF document. You can refer to the code of the ChartView struct below:

struct ChartView: View {
    let chartData = [ (city: "Hong Kong", data: hkWeatherData),
                      (city: "London", data: londonWeatherData),
                      (city: "Taipei", data: taipeiWeatherData)

    var body: some View {
        VStack {
            Text("Building Line Charts in SwiftUI")
                .font(.system(size: 40, weight: .heavy, design: .rounded))

            Chart {
                ForEach(chartData, id: \.city) { series in
                    ForEach(series.data) { item in
                            x: .value("Month", item.date),
                            y: .value("Temp", item.temperature)
                    .foregroundStyle(by: .value("City", series.city))
                    .symbol(by: .value("City", series.city))
            .chartXAxis {
                AxisMarks(values: .stride(by: .month)) { value in
                    AxisValueLabel(format: .dateTime.month(.defaultDigits))


            .chartPlotStyle { plotArea in
            .chartYAxis {
                AxisMarks(position: .leading)
            .frame(width: 350, height: 300)


            Text("Figure 1. Line Chart")


Saving the Chart View as a PDF Document Using ImageRenderer

What we are going to do is to create a PDF document for the ChartView using ImageRenderer. While it only takes a couple lines of code to convert a SwiftUI view into an image, we need a little more work for PDF rendering.

For image conversion, you can access the uiImage property to get the rendered image. To draw the chart into a PDF, we will use the render method of ImageRenderer. Here is what we are going to implement:

  • Look for the document directory and prepare the rendered path for the PDF file (e.g. linechart.pdf).
  • Prepare an instance of CGContext for drawing.
  • Call the render method of the renderer to render the PDF document.

For the implementation, we create a new method named exportPDF. Below is the code of the method :

private func exportPDF() {
    guard let documentDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first else { return }

    let renderedUrl = documentDirectory.appending(path: "linechart.pdf")

    if let consumer = CGDataConsumer(url: renderedUrl as CFURL),
       let pdfContext = CGContext(consumer: consumer, mediaBox: nil, nil) {

        let renderer = ImageRenderer(content: chartView)
        renderer.render { size, renderer in
            let options: [CFString: Any] = [
                kCGPDFContextMediaBox: CGRect(origin: .zero, size: size)

            pdfContext.beginPDFPage(options as CFDictionary)


    print("Saving PDF to \(renderedUrl.path())")

The first two lines of the code retrieves the document directory of the user and set up the file path of the PDF file (i.e. line chart.pdf). We then create the instance of CGContext. The mediaBox parameter is set to nil. In this case, Core Graphics uses a default page size of 8.5 by 11 inches (612 by 792 points).

The renderer closure receives two parameters: the current size of the view, and a function that renders the view to the CGContext. To begin the PDF page, we call the context’s beginPDFPage method. The renderer method draws the chart view. And remember that you need to close the PDF document to complete the whole operation.

To call this exportPDF method, we create a PDF button like this:

Button {
} label: {
    Label("PDF", systemImage: "doc.plaintext")

You can run the app in a simulator to have a test. After you tap the PDF button, you should see the following message in the console:

Saving PDF to /Users/simon/Library/Developer/CoreSimulator/Devices/CA9B849B-36C5-4608-9D72-B04C468DA87E/data/Containers/Data/Application/04415B8A-7485-48F0-8DA2-59B97C2B529D/Documents/linechart.pdf

If you open the file in Finder, you should see a PDF document like below.


To adjust the position of the drawing, you can insert this line of code before calling renderer:

pdfContext.translateBy(x: 0, y: 200)

This will move the chart to the upper part of the document.


Make the PDF file available to the Files app

You may wonder why the PDF file can’t be found in the Files app. Before you can make the file available to the built-in Files app, you have to change a couple of the settings in Info.plist. Switch to Info.plist and add the following keys:

  • UIFileSharingEnabled – Application supports iTunes file sharing
  • LSSupportsOpeningDocumentsInPlace – Supports opening documents in place

Set the value of the keys to Yes. Once you enable both options, run the app on the simulator again. Open the Files app and navigate to the On My iPhone location. You should see the app’s folder. Inside the folder, you will find the PDF document.


If you are interested in diving deeper into SwiftUI, check out our Mastering SwiftUI book.

Read next