9

I'm using the below code to use QLPreviewcontroller to show some documents in my app,

let ql = QLPreviewController()
ql.dataSource = self
//ql.navigationItem.rightBarButtonItems = nil
ql.navigationItem.rightBarButtonItem = nil
presentViewController(ql, animated: true, completion: nil)

I don't want the share button in the right top of QLPreviewcontroller. I'd tried setting rightBarButtonItem to nil, but it's not working.

How can I hide that?

Nazik
  • 8,696
  • 27
  • 77
  • 123

10 Answers10

5

None of those solutions worked for me in Swift 3 for iOS 10. The issue is that the Share button is created after viewDidAppear method.

Here are the steps I followed to remove the share button :

1) Subclassed my QLPreviewController

2) Created a method to open my document in this subclass :

func show(controller: UIViewController, url: NSURL) {
    // Refreshing the view
    self.reloadData()
    // Printing the doc
    if let navController = controller.navigationController {
        navController.pushViewController(self, animated: true)
    }
    else {
        controller.show(self, sender: nil)
    }
}

3) In my viewDidLayoutSubviews, I created a dummy button item to replace the share button :

 override func viewDidLayoutSubviews() {
    navigationItem.rightBarButtonItems?[0] = UIBarButtonItem()
}

4) When I want to open a document in another VC, I call it like this :

 QLSubclass().show(controller: self, url: path as NSURL)

Note : Always call it this way, and not with a global variable you instantiated because you will always see the share button before it disappears.

Ugo Marinelli
  • 989
  • 1
  • 11
  • 18
  • While this works great on iPad.. the share button on the iPhone is not on the nabber but on the bottom. Any idea how to remove that ? I tried to remove the toolbar button but the share button still remains – spaceMonkey May 29 '17 at 10:13
  • Another solution , that worked great for me, is to create your own VC and to add as a subview the view of the QLPreviewController in it , so you get rid of the share button :) – Ugo Marinelli May 29 '17 at 12:50
  • in ios 11 when users tap navigation bar hides and when thy tap again it appears with share button! Any solution for that? – Besat Sep 14 '18 at 17:06
  • 1
    Why are you passing url? It seems that it's not used anywhere! – Besat Sep 14 '18 at 17:10
  • How to hide it in iOS12.0, for all new AR Quicklook? – nOOb iOS Nov 29 '18 at 13:29
  • iOS10.3 ,` navigationItem.rightBarButtonItems?[0] = UIBarButtonItem()` show " Thread 1: Fatal error: Index out of range" – leonardosccd Jul 21 '20 at 06:56
5
  1. Create a subclass of QLPreviewController

  2. Add the following code to it

Swift:

var toolbars: [UIView] = []

var observations : [NSKeyValueObservation] = []

    override func viewDidLoad() {
        super.viewDidLoad()

        navigationItem.setRightBarButton(UIBarButtonItem(), animated: false)

    }

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

        navigationController?.toolbar.isHidden = true

        if let navigationToobar = navigationController?.toolbar {
            let observation = navigationToobar.observe(\.isHidden) {[weak self] (changedToolBar, change) in

                if self?.navigationController?.toolbar.isHidden == false {
                     self?.navigationController?.toolbar.isHidden = true
                }
            }
            observations.append(observation)
        }

        toolbars = toolbarsInSubviews(forView: view)

        for toolbar in toolbars {

            toolbar.isHidden = true

            let observation = toolbar.observe(\.isHidden) { (changedToolBar, change) in
                if let isHidden = change.newValue,
                    isHidden == false {
                    changedToolBar.isHidden = true
                }
            }

            observations.append(observation)
        }
    }

    private func toolbarsInSubviews(forView view: UIView) -> [UIView] {

        var toolbars: [UIView] = []

        for subview in view.subviews {
            if subview is UIToolbar {
                toolbars.append(subview)
            }
            toolbars.append(contentsOf: toolbarsInSubviews(forView: subview))
        }
        return toolbars
    }
Stephan Bauer
  • 9,120
  • 5
  • 36
  • 58
  • iif U want iOS13 hide rightBarButtonItem need add this `navigationItem.rightBarButtonItem = UIBarButtonItem() ` in " override func viewDidLoad() " – leonardosccd Jul 21 '20 at 10:13
3
let previewController = QLPreviewController()
previewController.navigationItem.rightBarButtonItem = UIBarButtonItem()
self.present(previewController, animated: true, completion: { })
Atul Pol
  • 341
  • 3
  • 5
  • I think what they are trying to convey is that if you assign `rightBarbuttonItem` to a new instance of `UIBarButtonItem` (without any further configuration) it would achieve the result. – The Muffin Man Feb 24 '20 at 22:47
  • IMO this is a great answer! – Fred Faust Jun 09 '20 at 16:36
  • 2
    doesn't work. If you apply this code then QLPreviewController will show a toolbar at the bottom with the same share button you just removed form the top right of the navigation bar. – zumzum Jul 01 '20 at 16:16
  • This does not work. Tested on iPad (iOS 16.3). – Darkwonder Feb 27 '23 at 07:26
2

I know this is an old question but I spend so many hours looking for a solution and came up with something that works.

So, for any one looking for the same thing as me. Here's my solution.

Codes are in objective-c but it'l be a simple conversion to Swift

First we create subclass of QLPreviewController and in the subclass override the following methods

Edit

Swift:

override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)
    self.navigationItem.rightBarButtonItem = nil
    //For ipads the share button becomes a rightBarButtonItem
    self.navigationController?.toolbar?.isHidden = true
    //This hides the share item
    self.navigationController?.toolbar?.addObserver(self, forKeyPath: "hidden", options: NSKeyValueObservingOptionPrior, context: nil)
}

override func viewWillDisappear(_ animated: Bool) {
    super.viewWillDisappear(animated)
    self.navigationController?.toolbar?.removeObserver(self, forKeyPath: "hidden")
}

override func observeValue(forKeyPath keyPath: String, ofObject object: Any, change: [AnyHashable: Any], context: UnsafeMutableRawPointer) {
    var isToolBarHidden: Bool? = self.navigationController?.toolbar?.isHidden
    // If the ToolBar is not hidden
    if isToolBarHidden == nil {
        DispatchQueue.main.async(execute: {() -> Void in
            self.navigationController?.toolbar?.isHidden = true
        })
    }
}

self.navigationController?.pushViewController(qlPreviewController, animated: true)

Objective-C:

-(void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
    self.navigationItem.rightBarButtonItem = nil; //For ipads the share button becomes a rightBarButtonItem
    [[self.navigationController toolbar] setHidden:YES]; //This hides the share item
    [[self.navigationController toolbar] addObserver:self forKeyPath:@"hidden" options:NSKeyValueObservingOptionPrior context:nil];
}

Remove the Observer on viewWillDisappear

-(void)viewWillDisappear:(BOOL)animated {
    [super viewWillDisappear:animated];
    [[self.navigationController toolbar] removeObserver:self forKeyPath:@"hidden"];
}

And the observer method: Required because when you single tap the image to hide the navigation bar and toolbar, the share button becomes visible again on tap.

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context{

    BOOL isToolBarHidden = [self.navigationController toolbar].hidden;
    // If the ToolBar is not hidden
    if (!isToolBarHidden) {
        dispatch_async(dispatch_get_main_queue(), ^{
            [[self.navigationController toolbar] setHidden:YES];
        });
    }
}

And the PreviewController has to be pushed from you existing navigationController

[self.navigationController pushViewController:qlPreviewController animated:YES];

And also we have to use the subclass instead of QLPreviewController.

moz ado
  • 490
  • 4
  • 17
  • Works for me. Did you find a way to hide the whole toolbar also? This only hides the share icon. – Henrik Hansen Feb 08 '17 at 12:15
  • There's a post on SO here [link](http://stackoverflow.com/questions/15811834/qlpreviewcontroller-hide-bottom-toolbar). Removes the toolbar but the share button becomes visible. Check it and if you come up with a solution please post your solution as well. – moz ado Feb 08 '17 at 12:31
  • it's only an issue in ios 10 it seems, maybe a bug that will be fixed. Before 10 it's hidden. – Henrik Hansen Feb 08 '17 at 13:06
  • in ios 11 when users tap navigation bar hides and when thy tap again it appears with share button! Any solution for that? – Besat Sep 14 '18 at 17:06
  • This solution didnt work for me on iPadOS 16 (iPad). – Darkwonder Feb 27 '23 at 07:35
1

If Still, anyone wants to remove share option or want to customize the Navigation bar of QLPreviewController then they can try creating a UIViewController and customize it as per requirement and then create QLPreviewController object and add it as a child view controller.

This will allow you to get rid of share button and you customize navigation bar color etc. this is working for me.

To know, how to add child view controller you can refer to this

Madan gupta
  • 668
  • 6
  • 19
1

Swift 5 Solution:

Subclass QLPreviewController:

final class CustomQLPreviewController: QLPreviewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        navigationItem.rightBarButtonItem = UIBarButtonItem()
    }

    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        (children[0] as? UINavigationController)?.setToolbarHidden(true, animated: false)
    }

    override func viewDidLayoutSubviews() {
        super.viewDidLayoutSubviews()
        (children[0] as? UINavigationController)?.setToolbarHidden(true, animated: false)
    }
}

then present this subclass where you want like this:

let previewController = QLVideoController()
present(controller, animated: true, completion: nil)
  • Using this method you will se share button for moments
Ali Moazenzadeh
  • 584
  • 4
  • 13
0
override func viewDidLoad() {
    super.viewDidLoad()
    /* Move "Share" Button to bottom */
    navigationItem.rightBarButtonItem = UIBarButtonItem()
}

override func viewWillLayoutSubviews() {
    super.viewWillLayoutSubviews()
    /* Hide toolbar to hide "Share" button  */
    self.navigationController?.toolbar.isHidden = true
}
sumsong
  • 1
  • 1
  • override func viewWillLayoutSubviews() { super.viewWillLayoutSubviews() navigationController?.toolbar.isHidden = true navigationItem.rightBarButtonItem = nil } – sumsong Mar 25 '21 at 04:09
  • 3
    Welcome to SO and thanks for contributing! It's often helpful if you provide some additional context around code snippets explaining what they do and/or how they answer the question. Links to sources or references are also helpful for those trying to adapt your code to slightly different situations. – Matthew Mar 25 '21 at 06:24
  • This answer is ineffective. – grantespo May 19 '21 at 14:57
0

This is the best solution I came up with.

The trick is to set the animation to true when hiding the toolbar. Otherwise we will see the share button shown then disappeared.

final class NoSharePreviewController: QLPreviewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        navigationItem.rightBarButtonItem = UIBarButtonItem()
    }

    override func viewDidLayoutSubviews() {
        super.viewDidLayoutSubviews()
        navigationController?.setToolbarHidden(true, animated: true)
    }
}
Devo
  • 1,004
  • 11
  • 10
-1

this work for me

   class QLSPreviewController : QLPreviewController {

        override func viewDidLoad() {
            super.viewDidLoad()



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

        }
        override func viewDidAppear(_ animated: Bool) {
            super.viewDidAppear(true )
            //This hides the share item
            let add =  self.childViewControllers.first as! UINavigationController
            let layoutContainerView  = add.view.subviews[1] as! UINavigationBar
             layoutContainerView.subviews[2].subviews[1].isHidden = true

        }
    }
-1

Swift5 elegant solution:

class QLPreviewVC: QLPreviewController {
    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        if let add = self.children.first as? UINavigationController {
            if let navBar = add.view.subviews.compactMap({ $0 as? UINavigationBar }).first {
                navBar.topItem?.rightBarButtonItem?.isHidden = true
            }
        }
    }
}

private extension UIBarButtonItem {
    var isHidden: Bool {
        get {
            return !isEnabled && tintColor == .clear
        }
        set {
            tintColor = newValue ? .clear : nil
            isEnabled = !newValue
        }
    }
}