【问题标题】:Presenting UIDocumentInteractionController with UIViewControllerRepresentable in SwiftUI在 SwiftUI 中使用 UIViewControllerRepresentable 呈现 UIDocumentInteractionController
【发布时间】:2020-06-06 19:54:56
【问题描述】:

我正在尽可能使用 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 应用程序上全屏显示吗? 谢谢

【问题讨论】:

    标签: ios swift iphone uikit swiftui


    【解决方案1】:

    我最终做了类似以下的事情,因为我无法使用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")
          })
      }
    }
    
    

    【讨论】:

      【解决方案2】:

      这是集成 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()
          }
      }
      

      【讨论】:

      • 终于开始测试了,效果非常好。谢谢!
      • 快速其他问题,对这个类似的 Asperi 有什么想法吗?谢谢。 stackoverflow.com/questions/61424672/…
      • 这也抱怨视图没有呈现在堆栈上
      • @Asperi 上面的代码sn-p中是否可以动态传递URL?我有一个用例,我通过网络请求获取动态 URL,我需要构建预览。显示预览时,视图控制器的视图并未添加到窗口层次结构中,因此视图是空白且透明的。
      • @Asperi 我很抱歉,我的逻辑已经解决了。我只有一个困惑。为了让它工作,为什么在这种情况下我们必须添加DocumentPreview 视图作为按钮的背景?为什么视图作为独立视图添加到VStack时不起作用?
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-10-18
      • 1970-01-01
      • 2020-12-28
      • 2023-02-21
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多