0
votes

I am subclassing QLPreviewController in my application and using the following code.

QLPreviewControllerSubClass* preview = [[QLPreviewControllerSubClass alloc] init];
  [self presentViewController:preview
                       animated:YES
                     completion:^()
                    {
                         // do more stuff here
                     }];

I want to hide the right bar button .Tried

-(void)viewDidAppear:(BOOL)animated{
    [super viewDidAppear:animated];
    [self navigationItem].rightBarButtonItems = nil;
}

But its not hiding.Any help will be appreciable

8

8 Answers

1
votes

I'm dealing the same problem also.

I made the rightBarButton hidden, but may have some problem when the loading of pdf lasts for a long time.

Below is my process.

1.Make a sub class of QLPreviewController.

2.Add a timer to repeats setting the rightBarButton to nil when the class init.

_hideRightBarButtonTimmer = [NSTimer scheduledTimerWithTimeInterval:0.01
                                                                 target:self
                                                               selector:@selector(hideRightButton)
                                                               userInfo:nil
                                                                repeats:YES];

3.Invalidate the timer in viewDidAppear.

[NSTimer scheduledTimerWithTimeInterval:5 target:self selector:@selector(cancelTimmer) userInfo:nil repeats:NO];

And I found the rightBarButton is setup while the loading of pdf file is finished. If we can detect the event the solution will be much easier and clearer.

Hopes it will be helpful.

1
votes

Its simple and working well import quicklook and create a class of QL-Click here for Result which u all need, working well

import UIKit
import QuickLook.
class QLSubclass: QLPreviewController , QLPreviewControllerDataSource {

var p = NSURL()
override func viewDidLoad() {
    super.viewDidLoad()
}
override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)
}
override func viewDidLayoutSubviews() {
    navigationItem.rightBarButtonItems?[0] = UIBarButtonItem()
}
func show(controller: UIViewController, url: NSURL) {
    // Refreshing the view
    p = url
    self.dataSource = self
    self.reloadData()
    // Printing the doc
    if let navController = controller.navigationController {
        navController.pushViewController(self, animated: true)
    }
    else {
        controller.show(self, sender: nil)
    }
}
func previewController(_ controller: QLPreviewController, previewItemAt index: Int) -> QLPreviewItem {
    let doc = p
    return doc
}
func numberOfPreviewItems(in controller: QLPreviewController) -> Int {
    return 1
}

}

after then in your view controller class-

class PatternVC: UIViewController, UIDocumentInteractionControllerDelegate , UINavigationControllerDelegate {

var link = ""
override func viewDidLoad() {
    super.viewDidLoad()
    let url = "YOUR_URL_LINK"
  //check file exist in local or not------
    if  isFileExist(imgURL: url) {
     //Found then show
        let loadPath = loadDataFromDirectory(imgURL: url)
        showFileWithPath(path: loadPath)
    }else {
        //save in local
        saveDataOnDocumentDirectory(imgURL: url)
    }
}
override func viewDidLayoutSubviews() {
    self.navigationController?.setNavigationBarHidden(true, animated: false)
}
override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
}//Open data
func showFileWithPath(path: String){
    let isFileFound:Bool? = FileManager.default.fileExists(atPath: path)
    if isFileFound == true{
        QLSubclass().show(controller: self, url: URL(fileURLWithPath: path) as NSURL)
    }else{}}

Also add a function for save in local in your view controller- //downloading request-----

private var downloadTask: URLSessionDownloadTask?
func saveDataOnDocumentDirectory(imgURL: String) {
    //let url = URL(string: imgURL)
    let escapedAddress = imgURL.addingPercentEncoding(withAllowedCharacters: CharacterSet.urlQueryAllowed)
    let url2 = URL(string: escapedAddress!)
    let sessionConfig = URLSessionConfiguration.default
    //let sessionConfig = URLSessionConfiguration.background(withIdentifier: "backgroundSession")
    let session: URLSession! = URLSession(configuration: sessionConfig, delegate: self, delegateQueue:  nil)
    downloadTask = session.downloadTask(with: url2!)
    downloadTask?.resume()
    DispatchQueue.main.async {
    }
}}

After that includes a extension on view extension PatternVC: URLSessionDelegate, URLSessionDownloadDelegate{

func urlSessionDidFinishEvents(forBackgroundURLSession session: URLSession) {

}
func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?) {
    if error != nil {
        // lbl.text = "Download failed"
    }
    resetView()
}
func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didFinishDownloadingTo location: URL) {
    let fileManager = FileManager.default
    do {
        let requestURL = downloadTask.currentRequest?.url
        let documentDirectory = try fileManager.url(for: .documentDirectory, in: .userDomainMask, appropriateFor:nil, create:true)
        let fileURL = documentDirectory.appendingPathComponent(getImageNameFromUrl(imgURL: requestURL!))
        do {

            try fileManager.moveItem(at: location, to: fileURL)
            print("save item: \(fileURL)")
        } catch (let writeError) {
            print("Error creating a file \(fileURL) : \(writeError)")
        }
    } catch {
        print(error)
    }
    DispatchQueue.main.async {
        //self.loadDirectory()
        self.resetView()
    }
}
func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didWriteData bytesWritten: Int64, totalBytesWritten: Int64, totalBytesExpectedToWrite: Int64) {
    // 1
    //guard let _ = downloadTask.originalRequest?.url, let download = model?.imagePath  else { return }
    let progress = Float(totalBytesWritten) / Float(totalBytesExpectedToWrite)
    DispatchQueue.main.async {
        //self.radialView.ringProgress = CGFloat(progress * 100)
    }
    print("-URL: \(downloadTask.currentRequest?.url?.relativePath ?? "") ----Per: \(CGFloat(progress * 100))")
}
func resetView() {
    downloadTask!.cancel()
}
func isFileExist(imgURL: String) -> Bool{
    let path = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0] as String
    let url = NSURL(fileURLWithPath: path)
    let escapedAddress = imgURL.addingPercentEncoding(withAllowedCharacters: CharacterSet.urlQueryAllowed)
    let url2 = URL(string: escapedAddress!)
    if let pathComponent = url.appendingPathComponent(getImageNameFromUrl(imgURL: url2!)) {
        let filePath = pathComponent.path
        let fileManager = FileManager.default
        if fileManager.fileExists(atPath: filePath) {
            print("FILE AVAILABLE")
            return true
        } else {
            print("FILE NOT AVAILABLE")
            let url = APIConstant.videoJpgUrl + link
            //self.loadUrl (urlString:url)
            return false
        }
    } else {
        print("FILE PATH NOT AVAILABLE")
        return false
    }
}
func loadDataFromDirectory(imgURL: String) -> String
{
    let path = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0] as String
    let url = NSURL(fileURLWithPath: path)
    let escapedAddress = imgURL.addingPercentEncoding(withAllowedCharacters: CharacterSet.urlQueryAllowed)
    let url2 = URL(string: escapedAddress!)
    if let pathComponent = url.appendingPathComponent(getImageNameFromUrl(imgURL: url2!)) {
        let filePath = pathComponent.path
        let fileManager = FileManager.default
        if fileManager.fileExists(atPath: filePath) {
            print("FILE AVAILABLE")
            return filePath
        } else {
            print("FILE NOT AVAILABLE")
            let url = APIConstant.videoJpgUrl + link
            self.loadUrl (urlString:url)
            return filePath
        }
    }else
    {
        return "ERROO"
    }
}
func getImageNameFromUrl(imgURL: URL) -> String{
    let name = imgURL.lastPathComponent
    let result = name.substring(from: name.index(name.startIndex, offsetBy: 5))
    return result
}
0
votes

I have found a solution to disable (not hide) therightBarButtonItem in QLPreviewController

The solution works fine for me in iOS8 and iOS9

You simply need to subclass QLPreviewController and override the following methods, then use your subclass instead of the original QLPreviewController

- (void)viewDidLoad {
    [super viewDidLoad];

    // When coming back from background we make sure the share button on the rightbBarButtonItem is disabled
    __weak typeof(self) weakSelf = self;
    [[NSNotificationCenter defaultCenter] addObserverForName:UIApplicationDidBecomeActiveNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification * _Nonnull note) {
        weakSelf.navigationItem.rightBarButtonItem.enabled = NO;
    }];
}

- (void)dealloc {
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}

- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];

    self.navigationItem.rightBarButtonItem.enabled = NO; // Disable the share button
}

- (void)viewDidAppear:(BOOL)animated {
    [super viewDidAppear:animated];

    self.navigationItem.rightBarButtonItem.enabled = NO; // Disable the share button
}
0
votes

Tested on iOS 9 with swift.

Recently had to solve this issue and had trouble finding a way to hide this dang button. I finally managed to hide the right share button using an answer from this stackoverflow post.

Basically, you want to subclass QLPreviewController and call the inspectSubviewForView() function in your viewWillAppear() function. Once you find the navigation item containing the share button, you can remove it:

override func viewWillAppear(animated: Bool) {
    super.viewWillAppear(animated)

    // ** traverse subviews until we find the share button ** //
    inspectSubviewForView(self.view)
}

func inspectSubviewForView(view: UIView) {
    for subview in view.subviews {
        if subview is UINavigationBar {
            // ** Found a Nav bar, check for navigation items. ** //
            let bar = subview as! UINavigationBar

            if bar.items?.count > 0 {
                if let navItem = bar.items?[0] {
                    // ** Found the share button, hide it! ** //
                    hideRightBarItem(navItem)
                }
            }
        }
        if subview.subviews.count > 0 {
            // ** this subview has more subviews! Inspect them! ** //
            inspectSubviewForView(subview)
        }
    }
}

func hideRightBarItem(navigationItem: UINavigationItem) {
    // ** Hide/Remove the Share button ** //
    navigationItem.setRightBarButtonItem(nil, animated: false)
}

The previous poster from the above link warned that this may not get through apple's review process as you are accessing private APIs, so use at your own risk! Also if Apple updates the QLPreviewController in later versions of iOS this code may no longer work.

Still, this is the only solution that has worked for me. I hope it works for you too!

0
votes

Thanks to Matthew Kostelecky, i was able to hide the share button but i would like to add some details for those need this in universal apps with multiple files.

Firstly Matthew's answer works if you use QLPreviewController modally. If you push QLPreviewController from your navigation controller like this;

navigationController?.pushViewController(quickLookController, animated: true)

It wont be able to find any NavigationBar or ToolBar. You should call QLPreviewController modally like this;

presentViewController(quickLookController, animated: true, completion: nil)

Also if you are developing universal app and you have list of files to play. There will be another button(List Button);

In iPhones if you have multiple files, QLPreviewController will create toolbar to show "List Button" and "Share Button" and both of these will be on ToolBar.
In iPads both of these buttons are on NavigationBar and there is no ToolBar.

So addition to Matthew's answer you should search toolBar if you have multiple files in iphone;

 func inspectSubviewForView(view: UIView) {
    for subview in view.subviews {
        if subview is UINavigationBar {
            // ** Found a Nav bar, check for navigation items. ** //
            let bar = subview as! UINavigationBar

            if bar.items?.count > 0 {
                if let navItem = bar.items?[0] {
                    navItem.setRightBarButtonItem(nil, animated: false)
                }
            }
        }
        if subview is UIToolbar {
            // ** Found a Tool bar, check for ToolBar items. ** //
            let bar = subview as! UIToolbar
            if bar.items?.count > 0 {
                if let toolBarItem = bar.items?[0] {
                    toolBarItem.enabled = false
                }
            }
        }

        if subview.subviews.count > 0 {
            // ** this subview has more subviews! Inspect them! ** //
            inspectSubviewForView(subview)
        }
    }
}

This piece of code will hide share button on iPad and disable share button on iPhone.

Hope it helps to those still need it.

0
votes

Simple solution for this is add one dummy view to current viewController and Add QLPreviewControlle.view to dummy view .

 previewController = [[QLPreviewController alloc] init];
 previewController.dataSource = self;
 previewController.delegate = self;
 previewController.currentPreviewItemIndex = 0;

[self.ContentView addSubview:previewController.view];



- (IBAction)removeQPView:(id)sender {

    [previewController.view removeFromSuperview];
}
0
votes

Another way to achieve this is by subclassing UIToolbar and overriding setItems(_:animated:). You can return an empty array if you want to remove all or return only buttons you want to keep. Here is an example PreviewControllerHideBottomButtons

0
votes

Go for subclassing the QLPreviewController and use the below-mentioned code, that only works fine for me using Xcode 8.3.

override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        if let firstView = self.childViewControllers.first    {
            for view in firstView.view.subviews    {
                if view.isKind(of: UIToolbar.self) {
                    view.removeFromSuperview()
                }
            }
        }
    }