Представление UIDocumentInteractionController с помощью UIViewControllerRepresentable в SwiftUI - PullRequest
1 голос
/ 22 февраля 2020

Я создаю новое приложение iOS, используя SwiftUI, где это возможно. Тем не менее, я хочу иметь возможность создавать PDF с некоторыми данными. В аналогичном проекте без swiftUI я могу сделать это

let docController = UIDocumentInteractionController.init(url: "PATH_TO_FILE")
                        docController.delegate = self
                        self.dismiss(animated: false, completion: {
                            docController.presentPreview(animated: true)
                        })

и до тех пор, пока где-нибудь еще в контроллере вида у меня есть это:

func documentInteractionControllerViewControllerForPreview(_ controller: UIDocumentInteractionController) -> UIViewController {
        return self
    }

Я хорош для go , Я не могу понять, как применить это к UIViewControllerRepresentable и заставить его работать в SwiftUI. Должен ли мой UIViewControllerRepresentable быть целью UIViewController? Как мне тогда установить делегат и presentPreview? Будет ли это перекрывать любой вид и отображать полный экран поверх моего приложения SwiftUI, как и для моего стандартного приложения iOS? Спасибо

1 Ответ

1 голос
/ 26 февраля 2020

Здесь возможен подход к интеграции UIDocumentInteractionController для использования из представления SwiftUI.

demo

Полный код модуля. Протестировано с 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()
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...