Qlpreviewcontroller Showing File Then Going Blank in Swiftui

QLPreviewController showing file then going blank in SwiftUI

I finally got it to work – big thanks to Leo Dabus for his help in the comments.

Here's my currently working code:

@State private var isShowingDoc = false
@State private var isLoadingFile = false
@State private var fileURL: URL?

var body: some View {
Button {
let destination: DownloadRequest.Destination = { _, _ in
let documentsURL = FileManager.default.documentsDirectory
.appendingPathComponent(document.id.string)
.appendingPathComponent(document.name ?? "file.jpg")
return (documentsURL, [.removePreviousFile, .createIntermediateDirectories])
}
isLoadingFile = true
AF
.download(url, to: destination)
.responseURL { (response) in
self.isLoadingFile = false
guard let url = response.fileURL else { return }
isShowingDoc = true
self.fileURL = url
}
} label: {
VStack {
Text("download")
if isLoadingFile {
ActivityIndicator(style: .medium)
}
}
}
.sheet(isPresented: $isShowingDoc, onDismiss: { isShowingDoc = false }) {
QuickLookView(url: fileURL!)
}
}

with this QuickLookView: (mostly unchanged)

struct QuickLookView: UIViewControllerRepresentable {

var url: URL

func makeCoordinator() -> Coordinator {
Coordinator(self)
}

func updateUIViewController(_ viewController: UINavigationController, context: UIViewControllerRepresentableContext<Self>) {
(viewController.topViewController as? QLPreviewController)?.reloadData()
}

func makeUIViewController(context: Context) -> UINavigationController {
let controller = QLPreviewController()

controller.dataSource = context.coordinator
controller.reloadData()
return UINavigationController(rootViewController: controller)
}

class Coordinator: NSObject, QLPreviewControllerDataSource {
var parent: QuickLookView

init(_ qlPreviewController: QuickLookView) {
self.parent = qlPreviewController
super.init()
}

func numberOfPreviewItems(in controller: QLPreviewController) -> Int {
1
}

func previewController(_ controller: QLPreviewController, previewItemAt index: Int) -> QLPreviewItem {
self.parent.url as QLPreviewItem
}
}
}

As you can see, there's hardly any difference to my code from when I asked the question. Yesterday night, the fileURL was always nil for an unclear reason; yet, now it started working just fine. In exchange, the remote images in my list (not shown here) stopped working even though I haven't touched them, haha.

I don't know what's going on and what I even changed to make it work, but it works and I won't complain!

Quicklook/QLPreviewController shows a blank page instead of pdf on ios 8 but works fine on iOS7

This is actually a known issue in iOS 8 Beta 5.

See the URL under QuickLook
https://developer.apple.com/library/prerelease/ios/releasenotes/General/RN-iOSSDK-8.0/

QLPreviewController missing navigation bar in SwiftUI

QuickLook preview does not have own navigation controller, it is our responsibility to provided one.

Here is possible approach. Tested with Xcode 11.4 / iOS 13.4

demo

struct TestQLPreviewController: View {
@State private var showQuickLook = false

// just for demo - document.pdf is located in main bundle
@State private var selectedURL = Bundle.main.url(forResource: "document", withExtension: "pdf")
var body: some View {
Button("Show") { self.showQuickLook.toggle() }
.sheet(isPresented: $showQuickLook, onDismiss: {self.showQuickLook = false}) {
if self.selectedURL != nil {
QuickLookController(url: self.selectedURL!) {
self.showQuickLook = false
}
}
}
}
}

struct QuickLookController: UIViewControllerRepresentable {

var url: URL
var onDismiss: () -> Void

func makeCoordinator() -> Coordinator {
Coordinator(self)
}

func updateUIViewController(_ viewController: UINavigationController, context: UIViewControllerRepresentableContext<QuickLookController>) {
if let controller = viewController.topViewController as? QLPreviewController {
controller.reloadData()
}
}

func makeUIViewController(context: Context) -> UINavigationController {
let controller = QLPreviewController()

controller.dataSource = context.coordinator
controller.reloadData()
return UINavigationController(rootViewController: controller)
}

class Coordinator: NSObject, QLPreviewControllerDataSource {
var parent: QuickLookController

init(_ qlPreviewController: QuickLookController) {
self.parent = qlPreviewController
super.init()
}
func numberOfPreviewItems(in controller: QLPreviewController) -> Int {
return 1
}
func previewController(_ controller: QLPreviewController, previewItemAt index: Int) -> QLPreviewItem {
return self.parent.url as QLPreviewItem
}

}
}

How to fix: QuickLook shows black screen instead of the desired picture

The problem is that your QuickLookViewController never actually presents the quick look. You have a QLPreviewController but it just sits there, unused.

Since QLPreviewController is itself a view controller, I would suggest eliminating the QuickLookViewController and just show the QLPreviewController from the first view controller.

Presenting UIDocumentInteractionController with UIViewControllerRepresentable in SwiftUI

Here is possible approach to integrate UIDocumentInteractionController for usage from SwiftUI view.

demo

Full-module code. Tested with Xcode 11.2 / iOS 13.2

import SwiftUI
import UIKit

struct DocumentPreview: UIViewControllerRepresentable {
private var isActive: Binding<Bool>
private let viewController = UIViewController()
private let docController: UIDocumentInteractionController

init(_ isActive: Binding<Bool>, url: URL) {
self.isActive = isActive
self.docController = UIDocumentInteractionController(url: url)
}

func makeUIViewController(context: UIViewControllerRepresentableContext<DocumentPreview>) -> UIViewController {
return viewController
}

func updateUIViewController(_ uiViewController: UIViewController, context: UIViewControllerRepresentableContext<DocumentPreview>) {
if self.isActive.wrappedValue && docController.delegate == nil { // to not show twice
docController.delegate = context.coordinator
self.docController.presentPreview(animated: true)
}
}

func makeCoordinator() -> Coordintor {
return Coordintor(owner: self)
}

final class Coordintor: NSObject, UIDocumentInteractionControllerDelegate { // works as delegate
let owner: DocumentPreview
init(owner: DocumentPreview) {
self.owner = owner
}
func documentInteractionControllerViewControllerForPreview(_ controller: UIDocumentInteractionController) -> UIViewController {
return owner.viewController
}

func documentInteractionControllerDidEndPreview(_ controller: UIDocumentInteractionController) {
controller.delegate = nil // done, so unlink self
owner.isActive.wrappedValue = false // notify external about done
}
}
}

// Demo of possible usage
struct DemoPDFPreview: View {
@State private var showPreview = false // state activating preview

var body: some View {
VStack {
Button("Show Preview") { self.showPreview = true }
.background(DocumentPreview($showPreview, // no matter where it is, because no content
url: Bundle.main.url(forResource: "example", withExtension: "pdf")!))
}
}
}

struct DemoPDFPreview_Previews: PreviewProvider {
static var previews: some View {
DemoPDFPreview()
}
}


Related Topics



Leave a reply



Submit