-1

I have a modal view on top of a navigation controller.

I wish to destroy the whole stack and re-create a new one (reload).

However, when assigning the new one to window.rootViewController, warnings appears during runtime and view controllers are not deallocated.

To make things more complicated, I am auto navigating to the modal view controller 'automatically' upon reload, and that < iOS 12 and iOS 13 behaves differently.

I have attached a reprex that demonstrates the issues that will appear. E.g. if you run it as is, on iOS 13, you will see the counter jump from 1 to 3, while on iOS 12, it jumps from 1 to 2. Both are leaking memory (some or all view controllers are not being unloaded).

CyberMew
  • 1,159
  • 1
  • 16
  • 33
  • Try to create a [mcve]. Very difficult to try to help without knowing exactly what you are doing. – DonMag Oct 14 '19 at 12:08
  • @DonMag I have added the example project on GitHub that can repro my issues. Do refer to RVCtriggerVC. – CyberMew Oct 15 '19 at 03:22
  • I have also rewrote the issue so that it is simpler and clearer to understand. – CyberMew Oct 15 '19 at 04:15
  • OK - pretty confusing, as you have a `TriggerVC` (class `RVCTriggerVC`), but your `RVCNavRootVC` has a Storyboard ID of **"triggerVC"**. What is your goal? Do you want to start with "First Screen" as the NavVC root, button tap pushes to "Second Screen", button tap *presents* "Third Screen", and then button tap should what? Replace everything with "Third Screen" as the NavVC root? Or go back to original starting point? – DonMag Oct 15 '19 at 12:38
  • Bad naming on my part for the Storyboard ID, but that is correct. Start with "First Screen" as the NavVC root, button tap pushes to "Second Screen", button tap presents "Third Screen". Button tap in "Third Screen" will replace everything, and repeats, this time automated: "First Screen" as the NavVC root, auto push "Second Screen", auto presents "Third Screen". The previous 'chain' should be deallocated by this time. – CyberMew Oct 16 '19 at 01:03

1 Answers1

1

The main issue is that regardless of how you replace the view hierarchy, your presented VC will dismiss which will send a viewWillAppear message to your "pushedVC" ... at which point "pushedVC" will immediately load and re-present "triggerVC"

What you probably want to do is:

  • Leave jumpToModalVC equal to false, until you want to use it
  • On button tap in presented "triggerVC", dismiss the modal (self)
  • on completion of the dismiss, set jumpToModalVC to true and rebuild / reset your hierarchy

Note:

Chained calls to segues from each VC's viewWillAppear almost always leads to:

Unbalanced calls to begin/end appearance transitions

To avoid that, it's best to trigger the segues from viewDidAppear

If you want, you can add me as a "Collaborator" on your GitHub repo (my GitHub user ID is DonMag), and I can push the changes I made as a new branch.

DonMag
  • 69,424
  • 5
  • 50
  • 86
  • I found out that sometimes even in viewDidAppear it might not work until I give it some time (async + 0.1secs). I have added you as collaborator too. Thanks! – CyberMew Oct 16 '19 at 13:43
  • hmmm... tried to push my changes, but GitHub desktop is telling me I don't have permission... – DonMag Oct 16 '19 at 14:10
  • It still shows up as awaiting response. I believe you have to accept the invitation in your email first in order to push, let me know if you didn’t get the invite! – CyberMew Oct 16 '19 at 14:25
  • ugh... I rarely do that, and my email associated with GitHub is one I rarely check... I pushed a new branch to your project - give it a try. – DonMag Oct 16 '19 at 14:31
  • Thanks a lot, I saw the branch changes, I will be sure to check/test it out tomorrow! (It’s sleeping time over here) – CyberMew Oct 16 '19 at 14:43
  • I just went through the changes, and adopted it, and it works great. I guess as you mentioned, the reason why it jumped from 1 to 3 is because of the `jumpToModalVC` flag being set to `true` and triggered to create the modal VC in `view*Appear:` during `dismiss`. I did not know that using `dismiss` on the most root controller will also trigger subsequent VCs in `view*Appear` to be called, hence the `window.rootViewController` doing 'weird' unexpected things. In my actual project, I am now using it inversely, as a flag to not trigger it when I start the process to `dismiss`. I also did not... – CyberMew Oct 17 '19 at 01:19
  • ..know that performing segues in `viewWillAppear` will almost cause the unbalanced call warnings, so that is also something to take note of in the future. The VCs are also deallocated so that is great. I thought the 'weird' behaviours of setting `rootViewController` is the cause of my VCs not being deallocated but it seems that it is just memory leaks in my actual projects (especially weak/unowned `self` in closures people). Seems like I did not have to perform any dismiss/pop at all in order to get dealloc/assignment to work, and I can just assign the new VC to `window.rootViewController`... – CyberMew Oct 17 '19 at 01:26
  • .. that is, if I did not require the dismiss animation. All in all I learnt a few things while debugging this, thank you @DonMag! – CyberMew Oct 17 '19 at 01:27