iDevelopper / PBRevealViewController

A UIViewController subclass for revealing a left and/or right view controller above or below a main view controller.
MIT License
80 stars 16 forks source link

Is there any way to cache the MainViewControllers? #82

Closed pawansaran closed 4 years ago

pawansaran commented 4 years ago

When we open the menu and click on the cell which corresponds to the present MainViewController, the library still calls viewDidLoad i.e. initialization and deinitialization still happens. Is there a way to prevent this from happening? To take this even further, is there a way to cache all the MainViewControllers which have been opened so that the app looks very fast and unnecessary calls are avoided?

iDevelopper commented 4 years ago

It has nothing to do with the framework. Keep all the controllers you want in some properties. Instantiate the main view controller to push only if it does not exist. You can see this in the ExampleWithSwiftLibrary demo, in MenuTableViewController.swift.

Example, your menu view controller:

    var settingsNavigationController: UINavigationController?
    ...

    override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        tableView.deselectRow(at: indexPath, animated: true)

        let storyboard = UIStoryboard(name: "Main", bundle: nil)
        var controller: UIViewController?

        revealViewController()?.toggleAnimationType = animations[indexPath.row]

        if controllers[indexPath.row] == "SettingsNavigationController" {
            if self.settingsNavigationController == nil {
                self.settingsNavigationController = storyboard.instantiateViewController(withIdentifier: controllers[indexPath.row]) as? UINavigationController
            }
            revealViewController()?.pushMainViewController(settingsNavigationController!, animated:true)
        }
        ...
   }
pawansaran commented 4 years ago

Thanks for the prompt reply @iDevelopper . Actually I have a logic in place for the same. Just thought since this would be a universal requirement maybe it could be a part of the framework by default. Anyways here is the way I have implemented the logic in my Subclass of PBRevealViewController. It would be great if you could just confirm whether its error free and robust.

class RevealViewController: PBRevealViewController {
    ....
    override func pushMainViewController(_ mainViewController: UIViewController, animated: Bool) {
        //check if the current MainViewController is same as the new one to be presented
        if let newMainVCIdentifier = mainViewController.restorationIdentifier, let currentMainVCIdentifer = self.mainViewController?.restorationIdentifier, currentMainVCIdentifer == newMainVCIdentifier {
            self.hideLeftView(animated: true)
            return
        }
        super.pushMainViewController(mainViewController, animated: animated)
    }
}
iDevelopper commented 4 years ago

The framework is already testing if the main view controller to push is the same as the current, and in this case just hides the menu (left or right).

pawansaran commented 4 years ago

I tested in your example projects as well as created a demo project .The viewcontroller gets deinitialized and initialized even if the ViewController to push is same as current. Checked it by adding a print statement in viewDidLoad of MainViewControllers. Attaching the demo project I made.

PBRevealTest.zip

iDevelopper commented 4 years ago

Will have a look. Thanks.

pawansaran commented 4 years ago

I think the issue is , I am using PBRevealViewControllerSeguePushController for navigating via side menu cell clicks. That would initialize a new ViewController whenever its called. Now, even though the current main viewcontroller is the one we want to navigate to, but since a new instance of current main viewcontroller would be created by the segue, the references will be different. Thats why the check in _pushFromViewController would always return false

private func _pushFromViewController(_ fromViewController: UIViewController, toViewController: UIViewController, operation: PBRevealControllerOperation, animated: Bool) {
        let duration: TimeInterval = animated ? (isLeftViewOpen ? leftToggleAnimationDuration : rightToggleAnimationDuration) : 0.0
        if fromViewController == toViewController {
            if operation == .pushMainControllerFromLeft {
                hideLeftView(animated: true)
            }
            if operation == .pushMainControllerFromRight {
                hideRightView(animated: true)
            }
            return
        }
    ....
}

Let me know. Thanks

iDevelopper commented 4 years ago

Yes this is the expected behavior. When perform a segue, iOS create a new instance.

Use instantiate instead, if you do not already have a reference to your main view controller and push it.

pawansaran commented 4 years ago

Ok thanks for your help.