我正在尽可能地使用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
}
我可以走了。我无法解决的是如何将它应用到UIViewControllerRepresentable中,并让它在SwiftUI中工作。我的UIViewControllerRepresentable应该以成为UIViewController为目标吗?然后如何设置委托和presentPreview?这会覆盖任何视图并在我的SwiftUI应用程序上显示全屏,就像对我的标准iOS应用程序那样吗?谢谢
发布于 2020-02-26 19:22:21
下面是从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()
}
}
发布于 2021-11-09 17:32:07
最后,我做了类似的事情,因为我无法用UIViewControllerRepresentable
和上面的答案可靠地完成这个任务。您可能需要对其进行编辑/扩展,以便使用。
class DocumentController: NSObject, ObservableObject, UIDocumentInteractionControllerDelegate {
let controller = UIDocumentInteractionController()
func presentDocument(url: URL) {
controller.delegate = self
controller.url = url
controller.presentPreview(animated: true)
}
func documentInteractionControllerViewControllerForPreview(_: UIDocumentInteractionController) -> UIViewController {
return UIApplication.shared.windows.first!.rootViewController!
}
}
用法:
struct DocumentView: View {
@StateObject var documentController = DocumentController()
var body: some View {
Button(action: {
documentController.presentDocument(url: ...)
}, label: {
Text("Show Doc")
})
}
}
发布于 2022-11-18 11:07:23
使用QLPreviewController
我知道问题是关于UIDocumentInteractionController,的,但是如果您想要呈现一个PDF file
(例如),可以使用QLPreviewController。
本地文件
呈现本地文件:
import SwiftUI
struct DocView: View {
@State private var buttonPressed: Bool = false
var body: some View {
Button {
buttonPressed = true
} label: {
Text("Show PDF file")
}
.sheet(isPresented: $buttonPressed) {
let localURL = Bundle.main.url(forResource: "Example", withExtension: "pdf")!
PreviewController(url: localURL)
}
}
}
远程文件
如果需要显示远程文件,请使用看这个要点。
PreviewController
UIViewControllerRepresentable for QLPreviewController
。
import QuickLook
import SwiftUI
struct PreviewController: UIViewControllerRepresentable {
@Environment(\.dismiss) private var dismiss
let url: URL
func makeUIViewController(context: Context) -> UINavigationController {
let controller = QLPreviewController()
controller.dataSource = context.coordinator
controller.navigationItem.leftBarButtonItem = UIBarButtonItem(
barButtonSystemItem: .done, target: context.coordinator,
action: #selector(context.coordinator.dismiss)
)
let navigationController = UINavigationController(rootViewController: controller)
return navigationController
}
func updateUIViewController(_ uiViewController: UINavigationController, context: Context) {}
func makeCoordinator() -> Coordinator {
return Coordinator(parent: self)
}
class Coordinator: QLPreviewControllerDataSource {
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
}
@objc func dismiss() {
parent.dismiss()
}
}
}
https://stackoverflow.com/questions/60354684
复制相似问题