1
votes

In my application, I'm using the QuickLook framework to view the document files such as pdf, ppt, doc, etc. etc. But due to privacy concerns, I don't want that the user can share this document with others so please let me know how to disable/hide the share button and also the copy-paste option.

I know this question can be asked by a number of times and tried many solutions but nothing works for me

  1. hide share button from QLPreviewController
  2. UIDocumentInteractionController remove Actions Menu
  3. How to hide share button in QLPreviewController using swift?
  4. Hide right button n QLPreviewController?

Please suggest to me to achieve this.

Here is my demo code:

import UIKit
import QuickLook

class ViewController: UIViewController {
    
    lazy var previewItem = NSURL()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
    }
    
    @IBAction func displayLocalFile(_ sender: UIButton){
        
        let previewController = QLPreviewController()
        // Set the preview item to display
        self.previewItem = self.getPreviewItem(withName: "samplePDf.pdf")
        
        previewController.dataSource = self
        self.present(previewController, animated: true, completion: nil)
        
    }
    
    @IBAction func displayFileFromUrl(_ sender: UIButton){
        
        // Download file
        self.downloadfile(completion: {(success, fileLocationURL) in
            
            if success {
                // Set the preview item to display======
                self.previewItem = fileLocationURL! as NSURL
                // Display file
                let previewController = QLPreviewController()
                previewController.dataSource = self
                self.present(previewController, animated: true, completion: nil)
            }else{
                debugPrint("File can't be downloaded")
            }
        })
    }
    
    
    
    func getPreviewItem(withName name: String) -> NSURL{
        
        //  Code to diplay file from the app bundle
        let file = name.components(separatedBy: ".")
        let path = Bundle.main.path(forResource: file.first!, ofType: file.last!)
        let url = NSURL(fileURLWithPath: path!)
        
        return url
    }
    
    func downloadfile(completion: @escaping (_ success: Bool,_ fileLocation: URL?) -> Void){
        
        let itemUrl = URL(string: "https://images.apple.com/environment/pdf/Apple_Environmental_Responsibility_Report_2017.pdf")
        
        // then lets create your document folder url
        let documentsDirectoryURL =  FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
        
        // lets create your destination file url
        let destinationUrl = documentsDirectoryURL.appendingPathComponent("filename.pdf")
        
        // to check if it exists before downloading it
        if FileManager.default.fileExists(atPath: destinationUrl.path) {
            debugPrint("The file already exists at path")
            completion(true, destinationUrl)
            
            // if the file doesn't exist
        } else {
            
            // you can use NSURLSession.sharedSession to download the data asynchronously
            URLSession.shared.downloadTask(with: itemUrl!, completionHandler: { (location, response, error) -> Void in
                guard let tempLocation = location, error == nil else { return }
                do {
                    // after downloading your file you need to move it to your destination url
                    try FileManager.default.moveItem(at: tempLocation, to: destinationUrl)
                    print("File moved to documents folder")
                    completion(true, destinationUrl)
                } catch let error as NSError {
                    print(error.localizedDescription)
                    completion(false, nil)
                }
            }).resume()
        }
    }
    
}

//MARK:- QLPreviewController Datasource

extension ViewController: QLPreviewControllerDataSource {
    func numberOfPreviewItems(in controller: QLPreviewController) -> Int {
        return 1
    }
    
    func previewController(_ controller: QLPreviewController, previewItemAt index: Int) -> QLPreviewItem {
        controller.navigationItem.rightBarButtonItem = nil
        return self.previewItem as QLPreviewItem
    }
}


Please provide your suggestion to do so or any other framework to view different file formats.

Here is the image

1

1 Answers

1
votes

Find below adopted my approach to your code (with modifications to test locally, but the code should be clear). The idea is

a) to override, which is completely allowed by API, needed classes to intercept modification

b) to use intentionally own UINavigationController, as only one navigation controller can be in stack

So here is code:

// Custom navigation item that just blocks adding right items
class MyUINavigationItem: UINavigationItem {
    override func setRightBarButtonItems(_ items: [UIBarButtonItem]?, animated: Bool) {
        // forbidden to add anything to right
    }
}

// custom preview controller that provides own navigation item
class MyQLPreviewController: QLPreviewController {
    private let item = MyUINavigationItem(title: "")

    override var navigationItem: UINavigationItem {
        get { return item }
    }
}

class MyViewController : UIViewController, QLPreviewControllerDataSource {
    lazy var previewItem = NSURL()
    override func loadView() {
        let view = UIView()
        view.backgroundColor = .white

        // just stub testing code
        let button = UIButton(type: .roundedRect)
        button.frame = CGRect(x: 150, y: 200, width: 200, height: 20)
        button.setTitle("Show", for: .normal)
        button.addTarget(self, action: 
                         #selector(displayLocalFile(_:)), for: .touchDown)
        view.addSubview(button)
        self.view = view
    }

    @objc func displayLocalFile(_ sender: UIButton){

        let previewController = MyQLPreviewController() // << custom preview
        // now navigation item is fully customizable
        previewController.navigationItem.title = "samplePDF.pdf"
        previewController.navigationItem.leftBarButtonItem = 
            UIBarButtonItem(barButtonSystemItem: .done, target: self, 
                            action: #selector(closePreview(_:)))

        // wrap it into navigation controller
        let navigationController = UINavigationController(rootViewController: previewController)
        // Set the preview item to display
        self.previewItem = self.getPreviewItem(withName: "samplePDF.pdf")

        previewController.dataSource = self
        // present navigation controller with preview
        self.present(navigationController, animated: true, completion: nil)
    }

    @objc func closePreview(_ sender: Any?) {
        self.dismiss(animated: true) // << dismiss preview
    }

    func getPreviewItem(withName name: String) -> NSURL{

        //  Code to diplay file from the app bundle
        let file = name.components(separatedBy: ".")
        let path = Bundle(for: type(of: self)).path(forResource: file.first!, ofType: file.last!)
        let url = NSURL(fileURLWithPath: path!)

        return url
    }

    func numberOfPreviewItems(in controller: QLPreviewController) -> Int {
        return 1
    }

    func previewController(_ controller: QLPreviewController, previewItemAt index: Int) -> QLPreviewItem {
        return self.previewItem as QLPreviewItem
    }

}