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
Very curious. It works when you wrap your PreviewController in a NavigationStack like this:
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.
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:
You could eliminate the
TabView
altogether, and just have aQLPreviewController
(obviouslyUIViewControllerRepresentable
) with a data source whose count is greater than 1. That gives you a UI where you can swipe between previews. NoTabView
with a hidden page indicator is needed.I was wondering if the problem was
QLPreviewController
insideUIPageViewController
, but that works in UIKit. So you mighty consider doing that, and making theUIPageViewController
theUIViewControllerRepresentable
.