1

I have a BaseViewController and a SideMenu that uses my MenuViewController. There are many possible "Home" screens that all inherit from this same BaseViewController. MenuViewController also inherits from BaseViewController.

I would like an overlay to be shown on the home screen and then disappear when the Menu is no longer in focus. So far, I can only get the overlay to show, but not disappear.

The overlay disappears if I tap one of the menu items, which performs a segue to the appropriate subclass of BaseViewController (for example, the Home screen or Settings screen). This effectively refreshes the screen, and I think I could keep a reference to the caller and segue back to it if I can't find a better solution.

Things I have tried:

  • overlay.removeFromSuperview()
  • view.sendSubview(toBack: overlay)
  • overlay.isHidden = true
  • overlay.alpha = 0.0
  • Moving hideOverlay() into MenuViewController.
  • Using super.overlay within MenuViewController instead of simply overlay or self.overlay.

I can confirm that all lines of code are hit with breakpoints, but the overlay view does not go away. BaseViewController's viewWillAppear() is not called when I tap to make the menu go away, because its subclass is already in view (just pushed to the side a bit).

Here is a minimal reproducible example:

BASE VIEW CONTROLLER

import UIKit
import SideMenu

class BaseViewController: UIViewController {

    let overlay = UIView()

    override func viewDidLoad() {
        super.viewDidLoad()

        // Setup
        overlay.frame = self.view.frame
        overlay.backgroundColor = UIColor.clear
        overlay.alpha = 0.5
        overlay.isUserInteractionEnabled = false
        overlay.autoresizingMask = [.flexibleWidth, .flexibleHeight]
        view.addSubview(overlay)
    }

    // WORKS
    func showMenu() {
        // menuLeftNavigationController is MenuViewController.
        self.present(SideMenuManager.menuLeftNavigationController!, animated: true) {
            UIView.animate(withDuration: 0.2) {
                self.overlay.backgroundColor = Constants.Colors.overlayColor // Already defined.
    }

   // PROBLEM IS HERE
   func hideOverlay() {
       UIView.animate(withDuration: 0.2) {
            self.overlay.backgroundColor = UIColor.clear
            self.overlay.setNeedsLayout()
            self.overlay.layoutIfNeeded()

            self.view.setNeedsLayout()
            self.view.layoutIfNeeded()
      }
   }

}

MENU VIEW CONTROLLER

import UIKit
import SideMenu

class MenuViewController: BaseViewController, UITableViewDataSource, UITableViewDelegate {

    @IBOutlet weak var tableView: UITableView!

    override func viewDidLoad() {
        super.viewDidLoad()

        // Tableview boilerplate
    }

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

    // BREAKPOINTS CONFIRM THIS CODE EXECUTES.
    override func viewWillDisappear(_ animated: Bool) {
        self.hideOverlay()
    }
}
s_khillon
  • 81
  • 3
  • 7

1 Answers1

0

In viewWillDisappear when you call self.hideOverlay, you're calling that on your MenuViewController.

When showMenu() is called, you present the MenuViewController and then set the overlay background colour on the presenting view controller.

I guess, what you want to do here is in the completion of the MenuViewController, dismiss method do:

if let presentingViewController = self.presentingViewController as? BaseViewController {
    presentingViewController.hideOverlay()
}

Hopefully that makes sense?

nkh
  • 115
  • 4
  • Thanks for your help! Unfortunately, it seems like this check fails, as presentingViewController is UIViewController, not BaseViewController. Do you know why that might be? – s_khillon Oct 31 '18 at 22:23
  • In the code above the class where `self.present` is being called is named `BaseViewController`, the property `self.presentingViewController` will be typed as a `UIViewController`, but using the option cast `as?` should be successful. – nkh Oct 31 '18 at 23:05
  • You could try setting your `MenuViewController`'s `modalPresentationStyle` to `overCurrentContext`, as when you call `present` from your base class, it may be delegating the presentation to another view further up the heirarchy – nkh Oct 31 '18 at 23:09