【问题标题】:Hide right button n QLPreviewController?隐藏右侧按钮 n QLPreviewController?
【发布时间】:2014-04-09 04:58:41
【问题描述】:

我在我的应用程序中继承 QLPreviewController 并使用以下代码。

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

我想隐藏右栏按钮。试过了

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

但它没有隐藏。任何帮助都会很明显

【问题讨论】:

标签: ios qlpreviewcontroller


【解决方案1】:

我也在处理同样的问题。

我把 rightBarButton 隐藏了,但是长时间加载 pdf 时可能会出现问题。

下面是我的过程。

1.制作QLPreviewController的子类。

2.添加一个定时器,在类初始化时重复设置rightBarButton为nil。

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

3.使viewDidAppear中的定时器失效。

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

我发现在加载 pdf 文件完成时设置了 rightBarButton。如果我们能够检测到该事件,解决方案将更加容易和清晰。

希望对您有所帮助。

【讨论】:

    【解决方案2】:

    其简单好用的导入quicklook并创建一个QL-Click here for Result which u all need, working well的类

    导入 UIKit
    导入 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
    }
    

    }

    然后在您的视图控制器类中-

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

    还在视图控制器中添加一个本地保存功能- //下载请求-----

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

    之后包括视图扩展 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
    }
    

    【讨论】:

      【解决方案3】:

      我找到了在QLPreviewController 中禁用(不隐藏rightBarButtonItem 的解决方案

      该解决方案在 iOS8 和 iOS9 中对我来说效果很好

      您只需要继承QLPreviewController 并覆盖以下方法,然后使用您的子类代替原来的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
      }
      

      【讨论】:

      • @San9211 你能找到解决办法吗?
      【解决方案4】:

      在 iOS 9 上使用 swift 测试。

      最近不得不解决这个问题,但很难找到隐藏这个 dang 按钮的方法。我终于设法使用来自this stackoverflow post 的答案隐藏了正确的分享按钮。

      基本上,您希望继承 QLPreviewController 并在 viewWillAppear() 函数中调用 inspectSubviewForView() 函数。找到包含分享按钮的导航项后,您可以将其移除:

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

      上述链接中的前一张海报警告说,由于您正在访问私有 API,这可能无法通过苹果的审核流程,因此使用风险自负!此外,如果 Apple 在更高版本的 iOS 中更新 QLPreviewController,此代码可能不再有效。

      不过,这是唯一对我有用的解决方案。我希望它也对你有用!

      【讨论】:

        【解决方案5】:

        感谢 Matthew Kostelecky,我能够隐藏共享按钮,但我想为那些在具有多个文件的通用应用程序中需要此功能的人添加一些详细信息。

        如果您以模态方式使用 QLPreviewController,首先 Matthew 的回答有效。 如果您像这样从导航控制器推送 QLPreviewController;

        navigationController?.pushViewController(quickLookController, animated: true)
        

        它将无法找到任何 NavigationBar 或 ToolBar。 您应该像这样以模态方式调用 QLPreviewController;

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

        此外,如果您正在开发通用应用程序并且您有要播放的文件列表。会有另一个按钮(列表按钮);

        在 iPhone 中,如果您有多个文件,QLPreviewController 将创建工具栏以显示“列表按钮”和“共享按钮”,这两个都将在工具栏上。
        在 iPad 中,这两个按钮都在 NavigationBar 上,并且没有 ToolBar。

        所以除了 Matthew 的回答之外,如果您在 iphone 中有多个文件,您还应该搜索 toolBar;

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

        这段代码将隐藏 iPad 上的分享按钮并禁用 iPhone 上的分享按钮。

        希望它对那些仍然需要它的人有所帮助。

        【讨论】:

          【解决方案6】:

          对此的简单解决方案是将一个虚拟视图添加到当前 viewController 并将 QLPreviewControlle.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];
          }
          

          【讨论】:

            【解决方案7】:

            实现此目的的另一种方法是继承 UIToolbar 并覆盖 setItems(_:animated:)。如果要删除所有按钮或仅返回要保留的按钮,则可以返回一个空数组。这是一个例子PreviewControllerHideBottomButtons

            【讨论】:

              【解决方案8】:

              去继承QLPreviewController 并使用下面提到的代码,它只适用于我使用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()
                              }
                          }
                      }
                  }
              

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2012-09-11
                • 1970-01-01
                • 2016-05-29
                相关资源
                最近更新 更多