Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use UIDocumentInteractionController?

I have created a program that loads PDF files. I want when the user is editing that they can publish the file anywhere in PDF format.

Do I use UIDocumentInteractionController or use UIActivityViewController?

Here is the code:

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
    }
}
like image 708
Faisal Avatar asked Jan 30 '18 06:01

Faisal


3 Answers

Using UIDocumentInteractionController is quite easy. You just need to know the url of your file, then you present the menu:

/// 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"
    }

}
like image 88
sundance Avatar answered Nov 16 '22 01:11

sundance


I have tried and explained in detail about UIDocumentInteractionController. Refer this link if you want to check the details.

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

Code

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
    }
}

Calling

@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")
}

Note

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

Before your files can appear in the Files app, you must indicate that your app supports Open in Place and File Sharing Enabled. These options are configured using keys in your Info.plist file.

The first key is UIFileSharingEnabled, which enables iTunes sharing of files in your Documents folder.

The second key is LSSupportsOpeningDocumentsInPlace, which grants the local file provider access to files in your Documents folder.

Add these keys to your Info.plist and set their values to YES.

like image 29
Mansi Avatar answered Nov 16 '22 01:11

Mansi


Silly case but might help to someone.

To anyone who can't save files check if your controller is alive. My problem was that my UIDocumentInteractionController was destroyed after it was closed.

Here's how my function looked like:

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

The fix is to make sure that UIDocumentInteractionController is alive after it closes:

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
    }
}
like image 40
Valery Shamshin Avatar answered Nov 16 '22 03:11

Valery Shamshin