macosswiftuipdfkit

Why I cannot view the contents of a PDF file using the PDFKit in macOS?


I am trying to display a pdf file with the PDFKit and the NSViewRepresentable wrapper

The following code displays a grayed frame and not the contents of the selected pdf file

import SwiftUI
import AppKit
import PDFKit

struct ContentView: View {
  @State var pdfURL: URL? = nil
  
  var body: some View {
    VStack {
      Button {
        let panel = NSOpenPanel()
        panel.allowsMultipleSelection = false
        panel.canChooseDirectories = false
        if panel.runModal() == .OK {
          if let src = panel.url {
            pdfURL = src
          }
        }
      } label: {
        Text("Pick a PDF file")
      }
      PDFKitView(url: pdfURL)
        .scaledToFit()
    }
    .padding()
  }
}

#Preview {
    ContentView()
}

struct PDFKitView: NSViewRepresentable {
  let url: URL?
    
  func makeNSView(context: NSViewRepresentableContext<PDFKitView>) -> PDFView{
    let pdfView = PDFView()
    if let url = url {
      pdfView.document = PDFDocument(url: url)
    }
    return pdfView
  }
  
  func updateNSView(_ nsView: PDFView, context: NSViewRepresentableContext<PDFKitView>) {
  }
  
}

I cannot figure out what I am doing wrong. Here is a screenshot after picking a pdf file

Screenshot


Solution

  • In your current code, you only set the document on the PDFView during makeNSView, at which point url is nil.

    Instead, you can move the document setting code to updateNSView, which is called when the url parameter changes (as well as on the initial load after makeNSView).

    struct PDFKitView: NSViewRepresentable {
        let url: URL?
        
        func makeNSView(context: NSViewRepresentableContext<PDFKitView>) -> PDFView{
            PDFView()
        }
        
        func updateNSView(_ pdfView: PDFView, context: NSViewRepresentableContext<PDFKitView>) {
            if let url = url {
                pdfView.document = PDFDocument(url: url)
            }
        }
    }