首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >在UIDocumentInteractionController中用UIViewControllerRepresentable表示SwiftUI

在UIDocumentInteractionController中用UIViewControllerRepresentable表示SwiftUI
EN

Stack Overflow用户
提问于 2020-02-22 17:14:47
回答 3查看 3.3K关注 0票数 4

我正在尽可能地使用iOS创建一个新的SwiftUI应用程序。但是,我希望能够用一些数据生成一个PDF。在没有swiftUI的类似项目中,我可以这样做

代码语言:javascript
运行
复制
let docController = UIDocumentInteractionController.init(url: "PATH_TO_FILE")
                        docController.delegate = self
                        self.dismiss(animated: false, completion: {
                            docController.presentPreview(animated: true)
                        })

只要在视图控制器中的其他地方,我就可以这样做:

代码语言:javascript
运行
复制
func documentInteractionControllerViewControllerForPreview(_ controller: UIDocumentInteractionController) -> UIViewController {
        return self
    }

我可以走了。我无法解决的是如何将它应用到UIViewControllerRepresentable中,并让它在SwiftUI中工作。我的UIViewControllerRepresentable应该以成为UIViewController为目标吗?然后如何设置委托和presentPreview?这会覆盖任何视图并在我的SwiftUI应用程序上显示全屏,就像对我的标准iOS应用程序那样吗?谢谢

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2020-02-26 19:22:21

下面是从UIDocumentInteractionController视图中集成SwiftUI以供使用的可能方法。

全模块代码。用Xcode 11.2 / iOS 13.2测试

代码语言:javascript
运行
复制
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()
    }
}
票数 9
EN

Stack Overflow用户

发布于 2021-11-09 17:32:07

最后,我做了类似的事情,因为我无法用UIViewControllerRepresentable和上面的答案可靠地完成这个任务。您可能需要对其进行编辑/扩展,以便使用。

代码语言:javascript
运行
复制
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!
    }
}

用法:

代码语言:javascript
运行
复制
struct DocumentView: View {
  @StateObject var documentController = DocumentController()

  var body: some View {
      Button(action: {
          documentController.presentDocument(url: ...)
      }, label: {
          Text("Show Doc")
      })
  }
}
票数 5
EN

Stack Overflow用户

发布于 2022-11-18 11:07:23

使用QLPreviewController

我知道问题是关于UIDocumentInteractionController,的,但是如果您想要呈现一个PDF file (例如),可以使用QLPreviewController

本地文件

呈现本地文件:

代码语言:javascript
运行
复制
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

代码语言:javascript
运行
复制
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()
        }
    }
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/60354684

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档