我将尽可能使用SwiftUI创建一个新的iOS应用。但是,我希望能够生成包含一些数据的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
}
我很好。 我无法解决的是如何将其应用于UIViewControllerRepresentable并使它在SwiftUI中工作。我的UIViewControllerRepresentable是否应该成为UIViewController?然后如何设置委托和presentPreview?这会像我的标准iOS应用程序一样在我的SwiftUI应用程序上覆盖任何视图并全屏显示吗? 谢谢
答案 0 :(得分:5)
有一种方法可以集成UIDocumentInteractionController
以便在SwiftUI视图中使用。
全模块代码。经过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()
}
}