I'm using QuickLook and I did hide share button before, But on iOS 16, there is a new arrow within the title. it contents share button and save to file etc...
I want to hide the whole menu or all buttons
I didn't know how to hide it I tried to add
navigationController.navigationItem.titleMenuProvider = nil
navigationController.navigationItem.documentProperties = nil
But it doesn't work
My Current Code
class AppQLPreviewController: QLPreviewController {
var toolbars: [UIToolbar] = []
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
// Hide Toolbar(share button) on iOS15
navigationItem.rightBarButtonItems = [UIBarButtonItem(), UIBarButtonItem()]
self.navigationController?.toolbar.isHidden = true
for childVC in children {
childVC.navigationController?.setToolbarHidden(true, animated: false)
}
toolbars = findToolbarsInSubviews(forView: view)
for toolbar in toolbars {
toolbar.isHidden = true
toolbar.addObserver(self, forKeyPath: "hidden", options: .new, context: nil)
}
}
override func viewWillLayoutSubviews() {
super.viewWillLayoutSubviews()
navigationItem.rightBarButtonItems = [UIBarButtonItem(), UIBarButtonItem()]
self.navigationController?.toolbar.isHidden = true
for childVC in children {
childVC.navigationController?.setToolbarHidden(true, animated: false)
}
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
for toolbar in toolbars {
toolbar.removeObserver(self, forKeyPath: "hidden")
}
}
override var shouldAutorotate: Bool {
return true
}
private func findToolbarsInSubviews(forView view: UIView) -> [UIToolbar] {
var toolbars: [UIToolbar] = []
for subview in view.subviews {
if subview is UIToolbar {
toolbars.append(subview as! UIToolbar)
}
toolbars.append(contentsOf: findToolbarsInSubviews(forView: subview))
}
return toolbars
}
override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey: Any]?, context: UnsafeMutableRawPointer?) {
if let keyPath = keyPath,
let toolbar = object as? UIToolbar,
let value = change?[.newKey] as? Bool,
keyPath == "hidden" && value == false {
toolbar.isHidden = true
}
}
}
QuickLook UIViewControllerRepresentable
import SwiftUI
import QuickLook
struct QuickLook: UIViewControllerRepresentable {
let urls: [URL]
@Binding var isPresented: Bool
func makeUIViewController(context: Context) -> UINavigationController {
let controller = AppQLPreviewController()
controller.dataSource = context.coordinator
controller.navigationItem.leftBarButtonItem = UIBarButtonItem(barButtonSystemItem: .cancel, target: context.coordinator, action: #selector(context.coordinator.dismiss))
let navigationController = UINavigationController(rootViewController: controller)
navigationController.navigationBar.topItem?.titleMenuProvider = nil
navigationController.navigationBar.topItem?.documentProperties = nil
return navigationController
}
func updateUIViewController(_ uiViewController: UINavigationController, context: Context) {}
func makeCoordinator() -> Coordinator {
return Coordinator(parent: self)
}
class Coordinator: QLPreviewControllerDataSource {
let parent: QuickLook
init(parent: QuickLook) {
self.parent = parent
}
func numberOfPreviewItems(in controller: QLPreviewController) -> Int {
if !parent.urls.isEmpty {
if parent.urls.count > 1 {
return parent.urls.count
} else {
return 1
}
}
return 0
}
func previewController(_ controller: QLPreviewController, previewItemAt index: Int) -> QLPreviewItem {
if parent.urls.count > 1 {
return parent.urls[index] as QLPreviewItem
}
else {
return parent.urls.first! as QLPreviewItem
}
}
@objc func dismiss() {
self.parent.isPresented = false
}
}
}
My View
struct ContentView: View {
@State private var openQuickLook = false
@State private var urls: [URL] = [(Bundle.main.url(forResource: "cat1", withExtension: "jpg")!), (Bundle.main.url(forResource: "cat2", withExtension: "jpg")!)]
var body: some View {
VStack {
Button {
openQuickLook.toggle()
} label: {
Text("Open Quick Look")
}
}
.padding()
.fullScreenCover(isPresented: $openQuickLook) {
QuickLook(urls: urls, isPresented: $openQuickLook)
.ignoresSafeArea()
}
}
}
The current result is
My code hide share button on toolbar but on iOS 16 it appear on Title Menu with save to File and Photos, I want to hide Title Menu and share button, so the quick look only show image and title without the menu button
I tried also add this code inside viewWillAppear
if let subViews = self.view.subviews.first?.subviews.compactMap({$0 as? UINavigationBar}) {
if let navBar = subViews.first {
DispatchQueue.main.async {
if #available(iOS 16.0, *) {
navBar.topItem?.titleMenuProvider = nil
navBar.topItem?.documentProperties = nil
} else {
// Fallback on earlier versions
}
}
}
}
but nothing change title menu still appeared
Try this (a hacky workaround):
let preview = QLPreviewController()
preview.dataSource = self
self.present(preview, animated: true) {
if let subViews = preview.view.subviews.first?.subviews.compactMap({$0 as? UINavigationBar}) {
if let navBar = subViews.first {
DispatchQueue.main.async {
if #available(iOS 16.0, *) {
navBar.topItem?.titleMenuProvider = nil
navBar.topItem?.documentProperties = nil
} else {
// Fallback on earlier versions
}
}
}
}
}
Result:
Try executing the code after some delay, this should work.
Add the below code in the AppQLPreviewController
class:
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
DispatchQueue.main.asyncAfter(deadline: .now() + 0.2, execute: {
print("check")
self.navigationController?.navigationBar.topItem?.documentProperties = nil
self.navigationController?.navigationBar.topItem?.titleMenuProvider = nil
})
}