0

When a UINavigationController pushes a view controller into view, the nav controller creates its own instance of that view controller behind the scenes. Using this nav controller delegate:

extension Main_ProfileViewController: UINavigationControllerDelegate {

    // called just after the navigation controller displays a view controller’s view and navigation item properties
    open func navigationController(_ navigationController: UINavigationController, didShow viewController: UIViewController, animated: Bool) {
        print(viewController)
    }

}


That instance can be "determined". The console prints something like this:

<ElChapo.SomeRandomViewController: 0x7fbe8b003640>

That 14-character hash is different each time that view controller is pushed by the nav controller so clearly they are different instances each time. My question: is that specific instance somehow accessible without using singletons? By accessible, I mean accessible where I can run a delegate to it and call specific methods within that specific instance.

This is what I'm trying to accomplish:

To pop a navigation stack back to its root, I would execute this function from within the view controller at the top of the stack.

// pop to root
func popToRoot() {
    self.navigationController?.popToRootViewController(animated: true)
}

This method must be called from within that specific instance of that view controller. If I call popToRoot() from another object, like the tab bar, by passing a delegate to it, it doesn't work because the delegate needs to find that exact instance to execute the pop.

youareawaitress
  • 387
  • 2
  • 17
  • 1
    Take a read through this post: https://stackoverflow.com/questions/5210535/passing-data-between-view-controllers?rq=1 That should give you plenty of information. – DonMag Aug 22 '17 at 15:21
  • Could you explain why you need to call a delegate for a specific instance of a view controller? A `UIViewController` has a lifecycle. So, you can just use that in order to perform custom actions. In addition, if your model does not change, you can always recreate the controller with the same state each time you create a new instance of it. This can be achieved through injection. Otherwise you can use a controller coordinator in order to achieve what you want without using a singleton. The coordinator is a sort of entry point that stores the controllers the navigation controller will present. – Lorenzo B Aug 22 '17 at 15:29
  • As @DonMag stated, the answer to your question is Yes. If you give some further details about the exact feature you are trying to accomplish, we may be able to provide more helpful answers. – Stephen Aug 22 '17 at 15:30
  • This question is a branch from my last question: https://stackoverflow.com/questions/45808032/uinavigationcontroller-poptorootviewcontroller-method-cannot-be-called-by-a-dele/45810920#45810920 – youareawaitress Aug 22 '17 at 15:32
  • Please, provide all the needed information here. Thanks. – Lorenzo B Aug 22 '17 at 15:34
  • @LorenzoB post updated – youareawaitress Aug 22 '17 at 15:40
  • @thismeanswar - you need to follow-up on a single question, until you've explained what you want to do and you get a solution for it. Starting a new question that doesn't really ask or explain what you're going for doesn't help anybody. – DonMag Aug 22 '17 at 15:42

1 Answers1

1

The Nav controller doesn't "create its own instance", or at least that is a somewhat confused way of looking at it. It only appears that way if you are using storyboards. You can use a Navigation Controller without use of storyboards at all if you so wish, in which case you would manually instantiate a new View Controller to push onto the nav controller stack. If you use a storyboard, it will contain defined segue's which "cause" the next view controller to get pushed onto the stack. It is the segues in the storyboard that define which view controllers get created when. There is no need to create a singleton to "get to" the child view controllers pushed onto the navigation stack. Each time one is pushed onto the navigation controller's stack, by default it will be created, and when it is popped, unless you specifically maintain a strong reference to it (which would almost always be a bad idea) it will be destroyed.

If you haven't already subclassed your navigation view controller, do so, and in the subclass override the prepare(for:sender:) to be able from the navigation controller, to access an instance of the child view controller pushed onto the navigation controller's stack. If you want to access that view controller, either save a reference to it in that method, or, better, find it in the navigation controllers stack using one of the following properties of the navigation controller:

var topViewController: UIViewController?
var visibleViewController: UIViewController?
var viewControllers: [UIViewController]

BTW the reference number you refer to isn't a hash but rather the hexadecimal value of a pointer (e.g. to the memory address) of where the view controller object is stored, but as you say, distinct view controllers will have distinct hex values.

TheBasicMind
  • 3,585
  • 1
  • 18
  • 20
  • I went down a rabbit hole that I could not get out of. If you could look at this Gist and offer some input I would be forever indebted. https://gist.github.com/sconewolf/606a4de42988363a1801a900eb76be0e – youareawaitress Aug 23 '17 at 01:24