skip to Main Content

I cannot find a way to get QuickLook(QLPreviewController) to load a pdf inside of a SwiftUI TabView. Is there a way to make this work? It is specifically when I tell Tabview to be a .page View.

struct QuickLookView: View {
    @State private var url: URL = Bundle.main.url(forResource: "Sample-PDF", withExtension: "pdf")!
    @State private var tab: Int = 0
    var body: some View {
        NavigationStack {
            TabView(selection: $tab) {
                ForEach(0..<3) { num in
                    PreviewController(url: url).tag(num)
                }
            }
            .tabViewStyle(.page(indexDisplayMode: .never))
        }
    }
}
struct PreviewController: UIViewControllerRepresentable {
    let url: URL
    
    func makeUIViewController(context: Context) -> QLPreviewController {
        let controller = QLPreviewController()
        controller.dataSource = context.coordinator
        return controller
    }
    
    func updateUIViewController(
        _ uiViewController: QLPreviewController, context: Context) {}
    
    
    func makeCoordinator() -> Coordinator {
        return Coordinator(parent: self)
    }
    
    class Coordinator: NSObject, QLPreviewControllerDataSource, UIGestureRecognizerDelegate {
        
        let parent: PreviewController
        
        init(parent: PreviewController) {
            self.parent = parent
        }
        
        func numberOfPreviewItems(in controller: QLPreviewController) -> Int {
            return 1
        }
        
        func previewController(_ controller: QLPreviewController, previewItemAt index: Int) -> QLPreviewItem {
            return parent.url as NSURL
        }
    }
}

2

Answers


  1. Very curious. It works when you wrap your PreviewController in a NavigationStack like this:

    struct QuickLookView: View {
        @State private var url: URL = Bundle.main.url(forResource: "Sample-PDF", withExtension: "pdf")!
        @State private var tab: Int = 0
        
        var body: some View {
            TabView(selection: $tab) {
                ForEach(0..<3) { num in
                    NavigationStack {
                        PreviewController(url: url)
                    }   .tag(num)
                }
                
            }   .tabViewStyle(.page(indexDisplayMode: .never))
        }
    }
    

    Unfortunately, if you then add a NavigationStack to contain the TabView it stops working again. I hope someone else can shed some more light on this weird behaviour. You may want to file a bug at Apple.

    Login or Signup to reply.
  2. Yes, this is surprising. If the tab view style is .page it does not work, but .automatic does.

    Two possible work-arounds for a paged view of previews jumps out at me:

    1. You could eliminate the TabView altogether, and just have a QLPreviewController (obviously UIViewControllerRepresentable) with a data source whose count is greater than 1. That gives you a UI where you can swipe between previews. No TabView with a hidden page indicator is needed.

    2. I was wondering if the problem was QLPreviewController inside UIPageViewController, but that works in UIKit. So you mighty consider doing that, and making the UIPageViewController the UIViewControllerRepresentable.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search