如何使用 UIDocumentInteractionController?

How to use UIDocumentInteractionController?

我创建了一个加载 PDF 文件的程序。我希望当用户编辑时,他们可以将文件以 PDF 格式发布到任何地方。

我使用 UIDocumentInteractionController 还是使用 UIActivityViewController

代码如下:

import UIKit
import PDFKit

@available(iOS 11.0, *)
@available(iOS 11.0, *)

class PDFViewControllerEN: UIViewController {
    var document: UIDocumentInteractionController!

    override func viewDidLoad() {
        super.viewDidLoad()
        // retrieve URL to file in main bundle`
    }

    @IBOutlet var pdfview: UIView!

    @IBAction func share(_ sender: UIButton) {
    }

    @IBAction func doAction2(_ sender: UIBarButtonItem) {
        document.presentOptionsMenu(from: view.bounds, in: view, animated: true)
    }

    override func viewWillAppear(_ animated: Bool) {
        //Here you are going to display your PdfController
        //PDFController that is seprate class you had created to show pdf file being opened
        //i.e

        //check which button was being selected
        switch ButtonSelected.Tag {
        case 0:
            var document: UIDocumentInteractionController = {
                let pdfView = PDFView(frame: UIScreen.main.bounds)

                let url = Bundle.main.url(forResource: "EN1", withExtension: "pdf")

                let vc = UIDocumentInteractionController(url: url!)
                pdfView.document = PDFDocument(url: url!)
                view.addSubview(pdfView)
                vc.delegate = self

                return vc
            }()
            //  document.presentPreview(animated: true)
            break
        case 1:
            //here control when you selected button with tag 0
            //here need to open pdf AR2
            //set Frame here all bounds

            var document: UIDocumentInteractionController = {
                let pdfView = PDFView(frame: UIScreen.main.bounds)

                let url = Bundle.main.url(forResource: "EN2", withExtension: "pdf")

                let vc = UIDocumentInteractionController(url: url!)
                pdfView.document = PDFDocument(url: url!)
                view.addSubview(pdfView)
                vc.delegate = self

                return vc
            }()
            break
        case 2:
            //here control when you selected button with tag 0
            //here need to open pdf AR2
            //set Frame here all bounds

            var document: UIDocumentInteractionController = {
                let pdfView = PDFView(frame: UIScreen.main.bounds)

                let url = Bundle.main.url(forResource: "EN3", withExtension: "pdf")

                let vc = UIDocumentInteractionController(url: url!)
                pdfView.document = PDFDocument(url: url!)
                view.addSubview(pdfView)
                vc.delegate = self

                return vc
            }()
            break
        default:
            //Error Case
            print("No tag Value Available")
        }
    }
}

@available(iOS 11.0, *)
extension PDFViewControllerEN: UIDocumentInteractionControllerDelegate {
    func documentInteractionControllerViewControllerForPreview(_ controller: UIDocumentInteractionController) -> UIViewController {
        return self
    }
}

使用 UIDocumentInteractionController 非常简单。你只需要知道你的文件的url,然后你呈现菜单:

/// Needs to be global, otherwise the controller will be destroyed when the file is handed over to target application
var documentInteractionController: UIDocumentInteractionController!

class MyViewController: UIViewController {

    var url: URL

    ...

    @IBAction func share(_ sender: UIBarButtonItem) {
        documentInteractionController = UIDocumentInteractionController()
        documentInteractionController.url = url
        documentInteractionController.uti = url.uti
        documentInteractionController.presentOptionsMenu(from: sender, animated: true)
    }

}

extension URL {

    var uti: String {
        return (try? self.resourceValues(forKeys: [.typeIdentifierKey]))?.typeIdentifier ?? "public.data"
    }

}

关于UIDocumentInteractionController我已经尝试并详细解释了。如果您想查看详细信息,请参考此 link。

https://medium.com/if-let-swift-programming/managing-files-in-ios-dfcdfdc1f426

代码

extension ViewController {
    /// This function will set all the required properties, and then provide a preview for the document
    func share(url: URL) {
        documentInteractionController.url = url
        documentInteractionController.uti = url.typeIdentifier ?? "public.data, public.content"
        documentInteractionController.name = url.localizedName ?? url.lastPathComponent
        documentInteractionController.presentPreview(animated: true)
    }

    /// This function will store your document to some temporary URL and then provide sharing, copying, printing, saving options to the user
    func storeAndShare(withURLString: String) {
        guard let url = URL(string: withURLString) else { return }
        /// START YOUR ACTIVITY INDICATOR HERE
        URLSession.shared.dataTask(with: url) { data, response, error in
            guard let data = data, error == nil else { return }
            let tmpURL = FileManager.default.temporaryDirectory
                .appendingPathComponent(response?.suggestedFilename ?? "fileName.png")
            do {
                try data.write(to: tmpURL)
            } catch {
                print(error)
            }
            DispatchQueue.main.async {
                /// STOP YOUR ACTIVITY INDICATOR HERE
                self.share(url: tmpURL)
            }
            }.resume()
    }
}

extension ViewController: UIDocumentInteractionControllerDelegate {
    /// If presenting atop a navigation stack, provide the navigation controller in order to animate in a manner consistent with the rest of the platform
    func documentInteractionControllerViewControllerForPreview(_ controller: UIDocumentInteractionController) -> UIViewController {
        guard let navVC = self.navigationController else {
            return self
        }
        return navVC
    }
}

extension URL {
    var typeIdentifier: String? {
        return (try? resourceValues(forKeys: [.typeIdentifierKey]))?.typeIdentifier
    }
    var localizedName: String? {
        return (try? resourceValues(forKeys: [.localizedNameKey]))?.localizedName
    }
}

通话中

@IBAction func showOptionsTapped(_ sender: UIButton) {
    /// Passing the remote URL of the file, to be stored and then opted with mutliple actions for the user to perform
    storeAndShare(withURLString: "https://images5.alphacoders.com/581/581655.jpg")
}

备注

https://www.bignerdranch.com/blog/working-with-the-files-app-in-ios-11/

在您的文件可以出现在 Files 应用程序之前,您必须表明您的应用程序支持就地打开和启用文件共享。这些选项是使用 Info.plist 文件中的密钥配置的。

第一个键是 UIFileSharingEnabled,它允许 iTunes 共享您的文档文件夹中的文件。

第二个密钥是 LSSupportsOpeningDocumentsInPlace,它授予本地文件提供商访问您的文档文件夹中文件的权限。

将这些键添加到您的 Info.plist 并将它们的值设置为 YES。

愚蠢的案例,但可能对某人有所帮助。

对于无法保存文件的任何人,请检查您的控制器是否存在。我的问题是我的UIDocumentInteractionController关闭后就被销毁了。

我的函数如下所示:

private func showDocumentInteractionController(url: URL) {
     let documentInteractionController = UIDocumentInteractionController(url: url)
     documentInteractionController.presentOptionsMenu(from: view.frame, in: view, animated: true)
     documentInteractionController.delegate = self
}

解决方法是确保 UIDocumentInteractionController 在关闭后仍然存在:

class ViewController: UIViewController, UIDocumentInteractionControllerDelegate {
    private let documentInteractionController = UIDocumentInteractionController()

    private func showDocumentInteractionController(url: URL) {
       documentInteractionController.url = url
       documentInteractionController.presentOptionsMenu(from: view.frame, in: view, animated: true)
       documentInteractionController.delegate = self
    }
}

这应该可以显示 PDF 文件:

import UIKit

class ViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        
        DispatchQueue.main.asyncAfter(deadline: .now() + 1) { [self] in
            guard let path = Bundle.main.url(forResource: "YOUR_PDF_FILE_NAME_WITHOUT_EXTENSION", withExtension: "pdf") else { return }
            let documentInteractionController = UIDocumentInteractionController.init(url: path)
            documentInteractionController.delegate = self
            documentInteractionController.presentPreview(animated: true)
        }

    }
}

extension ViewController: UIDocumentInteractionControllerDelegate {
    func documentInteractionControllerViewControllerForPreview(_ controller: UIDocumentInteractionController) -> UIViewController {
        return self
    }
}