0

I have been fiddling with UINavigationController for while but this problem is a little tricky for me now,

I have a UINavigationController with three view controllers.

A -> B -> C

and when I come to C view controller in the viewDidLoad() I am removing B from the stack now if I tap back on C it goes to A, everything is working as expected but B never gets released but C does.

Removal code:

    if self.navigationController != nil{
        for viewController in (self.navigationController?.viewControllers)!{
            if viewController.isKindOfClass(MyVCKind.self){
                self.navigationController?.viewControllers.removeAtIndex((self.navigationController?.viewControllers.indexOf(viewController))!)
            }
        }
    }

So I tested and profiled B view controller just to be sure that I don't have anything leaking there, everything is fine when I go from B -> A by tapping back on B, B is getting flushed out but the problem is only when I am manually removing B from the stack.

FYI I don't want to set a custom back button and override the action, I want the default behavior and with no leaks.

Any help is appreciated.

Satheesh
  • 10,998
  • 6
  • 50
  • 93
  • To do that I need to override the back button and I don't want to do that. – Satheesh Sep 09 '16 at 06:17
  • When you are pushing the `C` from `B`, Then first pop the `B` without animation, and then push `C`. This will remove the B view controller without any leak. – pkc456 Sep 09 '16 at 06:21
  • @pkc456 It is not working! – Satheesh Sep 09 '16 at 06:52
  • You can just use delegate from B back to A and push from there to C, then B will get proper release, have you though about that yet? – Tj3n Sep 09 '16 at 07:56

2 Answers2

3

It was really weird that I have found another mysterious strong reference in making network calls in my app so that was the reason the second view controller was not getting flushed out after fixing that leak everything is working as expected. The below code just works fine.

 if self.navigationController != nil{
        for viewController in (self.navigationController?.viewControllers)!{
            if viewController.isKindOfClass(MyVCKind.self){
                self.navigationController?.viewControllers.removeAtIndex((self.navigationController?.viewControllers.indexOf(viewController))!)
            }
        }
    }
Satheesh
  • 10,998
  • 6
  • 50
  • 93
0

It's because (self.navigationController?.viewControllers returns non-mutable array (i.e. NSArray).

So, you can't remove object from it.

So, you can manage this scenario something like,

first get array of viewcontrollers then convert it to mutable array then remove desired object or viewcontroller from it and then set that array as viewcontrollers of your navigation controller

You can refer this so post also!

Update :

Another way :

   override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {


    self.removeFromParentViewController()

   //OR

    self.navigationController?.popViewControllerAnimated(false)


}
Community
  • 1
  • 1
Ketan Parmar
  • 27,092
  • 9
  • 50
  • 75
  • Not using segues, I am using navigationController push and pop. – Satheesh Sep 09 '16 at 06:52
  • One thing you can do that present `viewcontroller C` with animation like push and in `completion handler` of that presentVC method remove `viewController B`!! Or you can try `self.navigationController?.popViewControllerAnimated(false)` before you push new VC – Ketan Parmar Sep 09 '16 at 07:03