在SwiftUI中使用UIViewControllerRepresentable呈现UIDocumentInteractionController [英] Presenting UIDocumentInteractionController with UIViewControllerRepresentable in SwiftUI
问题描述
我将尽可能使用SwiftUI创建一个新的iOS应用.但是,我希望能够生成包含一些数据的PDF. 在没有swiftUI的类似项目中,我可以做到
I'm creating a new iOS app using SwiftUI where ever possible. However, I want to be able to generate a PDF with some data. In a similar project without swiftUI I can do this
let docController = UIDocumentInteractionController.init(url: "PATH_TO_FILE")
docController.delegate = self
self.dismiss(animated: false, completion: {
docController.presentPreview(animated: true)
})
,只要在视图控制器中的其他地方,我就会这样:
and as long as somewhere else in the view controller I have this:
func documentInteractionControllerViewControllerForPreview(_ controller: UIDocumentInteractionController) -> UIViewController {
return self
}
我很好. 我无法解决的是如何将其应用于UIViewControllerRepresentable并使它在SwiftUI中工作.我的UIViewControllerRepresentable是否应该成为UIViewController?然后如何设置委托和presentPreview?这会像我的标准iOS应用程序一样在我的SwiftUI应用程序上覆盖任何视图并全屏显示吗? 谢谢
I'm good to go. What I can't work out is how to apply this to a UIViewControllerRepresentable and have it working in SwiftUI. Should my UIViewControllerRepresentable be aiming to be a UIViewController? How do I then set the delegate and presentPreview? Will this overlay any view and display full screen over my SwiftUI app as it does for my standard iOS app? Thanks
推荐答案
以下是将UIDocumentInteractionController
集成以在SwiftUI视图中使用的可行方法.
Here is possible approach to integrate UIDocumentInteractionController
for usage from SwiftUI view.
全模块代码.经过Xcode 11.2/iOS 13.2的测试
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()
}
}
这篇关于在SwiftUI中使用UIViewControllerRepresentable呈现UIDocumentInteractionController的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!