4

I have an app that is made up of a UINavigationController that pushes ViewControllers from 3 different tabs.

The trouble I am foreseeing is that current structure allows the user to endlessly add VC's onto the stack.

I have a tab called pharmaceuticals and another called pathogens. If you drill down far enough in pharmaceuticals you get to a list of the pathogens it is effective against and the user can select a pathogen to see more information about it. This causes the app to push a new pathogenVC.

Now the user can drill down to the list of pharmaceuticals the pathogen is susceptible to and select it, which cause a new VC in the pharmaceuticals tab.

and so on and so on...

each time there is an additional 1.5Mb added to the memory footprint.

How can I best manage this?

Michael Campsall
  • 4,325
  • 11
  • 37
  • 52
  • 1
    Where is that memory coming from? You should be reusing / unloading those resources when not being used (visible). – Wain Dec 18 '13 at 19:20
  • Are you only switching between these two tabs? If so, when going from the pathogens back to the pharmaceuticals, you could dismiss the current view controller. – Liftoff Dec 18 '13 at 19:20
  • The VC"s are UITableViewControllers and I am assuming the navigationcontroller is retaining them so it can navigate back to them in the same state it left them in. Is that not the case? – Michael Campsall Dec 18 '13 at 19:25
  • As for switching between the tabs, each one has a hierarchy of VC's within them. Though I have been thinking that if I do switch to a tab that already has VC's on the stack, maybe I could pop to the root VC for that tab only? (Not sure how this is done though) – Michael Campsall Dec 18 '13 at 19:26

2 Answers2

5

You should focus on minimizing your memory footprint by releasing resources you can easily re-create instead of trying to stop the user from pushing 100 view controllers onto your stack. Apple doesn't do that either.

Open the 'iTunes Store' app and search for "Hugh Laurie", select the album "Let Them Talk", then on "Hugh Laurie >", then on "Let Them Talk", then on "Hugh Laurie >" and so on. You can keep going and going and going. When the user does this for a very long time, the app will probably run out of memory and crash.

If you try to load 20 tons of bricks onto your Toyota Pickup, it will probably be crushed like an empty Capri Sun packet. This is intentional destructive behavior and IMHO it is OK for the app to terminate if the user forcefully tries to overload it.

enter image description here

However, you can make this point almost unreachable and thus this scenario very unlikely by releasing memory in your off-screen view controllers. Implement didReceiveMemoryWarning (example: How to implement didReceiveMemoryWarning?) to release things you can easily re-create from disk or the network (images, Core Data objects etc). That way, you can bring your memory footprint way down and your users will only be able to make your app crash if they have several hours on their hands and nothing better to do than to push view controllers. Which would be sad.

Community
  • 1
  • 1
Johannes Fahrenkrug
  • 42,912
  • 19
  • 126
  • 165
  • 2
    that truck looks just like my jetta on a trip to home depot! Point taken on the intentially destructive behaviour. It would be a shame to limit the navigation for likely 100% of cases just to accommodate the edge case of the sad VC pusher. And really, maybe that sad VC pusher needs to have the app crash for them so they can move on with their lives... – Michael Campsall Dec 18 '13 at 20:50
  • 1
    I can basically release everything in the VC's except a simple data object, so this might work very nicely. – Michael Campsall Dec 18 '13 at 20:53
  • So I tried to be a sad VC pusher and my brain could handle no more of the monotony and I wasn't even close to getting the app to use up all the memory. Responding to a text in the middle of the test freed up a lot of memory, and then subsequently exiting the app and returning also freed up a lot. I think the best solution here is to trust that iOS does a fine job of freeing up the memory when needed. I will also look for logical places to clear the stack of VC's. Thanks for your help. – Michael Campsall Dec 18 '13 at 23:25
2

You can implement your own UINavigationController subclass. You'll need to implement at least pushViewController:animated: and popViewControllerAnimated:. During a push, you'd discard one of the view controllers (thereby releasing the memory), and in pop, you'd create it again, using the data that you keep around. Basically, you'll switch from keeping the entire stack of view controllers to having just a couple elements, with the logic to restore the ones further down the stack.

This is a simplified description. In the actual app, you'll want to keep at least the previous view controller around, so that your back button and the swipe-from-the-edge back gesture work smoothly.

TotoroTotoro
  • 17,524
  • 4
  • 45
  • 76
  • Do navigationcontrollers keep track of which tab the VC's are associated with? If so, could I not just pop all the pathogen VC's if I am navigating back to that tab? EDIT: I had something confused: Tabbar controller and navigation controller, I see now that each tab has its own navigationcontroller which should make things much easier – Michael Campsall Dec 18 '13 at 19:36
  • I think you can do that, yes. But I thought your concern was about the case when the user keeps going deeper within a navigation controller without changing tabs? – TotoroTotoro Dec 18 '13 at 19:42
  • That is true, as it stands they are not switching tabs...just adding VC's. Maybe I need to programmatically switch tabs before pushing the VC's. The app should show that the user is in the pathogen tab when viewing the pathogen info. – Michael Campsall Dec 18 '13 at 19:44
  • BTW, you can access the tab bar controller through the UIViewController's `tabBarController` property. And each VC knows also its navigation controller, so you can connect the dots and see which VC is under which tab. – TotoroTotoro Dec 18 '13 at 19:44
  • 1
    "Maybe I need to programmatically switch tabs before pushing the VC's"-- now that sounds like a hack. If I were using an app, and it suddenly switched tabs on me, I wouldn't appreciate it at all :) – TotoroTotoro Dec 18 '13 at 19:46
  • I see your point, but the pathogen info VC is is exactly the same as the one from the pathogen tab, so it would be confusing if you were in the pharmaceutical tab and saw the pathogen information VC. – Michael Campsall Dec 18 '13 at 19:48
  • Now I see the trouble with switching tabs... the back button will not work, nor will the swipe from the side. – Michael Campsall Dec 18 '13 at 19:49
  • Yeah. The whole point of the solution I propose is to preserve the appearance and behavior of a regular navigation controller, but without the huge memory footprint when pushing too many VCs down the navigation stack. – TotoroTotoro Dec 18 '13 at 19:51
  • agreed. I will play around with it for a bit, thanks for all your help! – Michael Campsall Dec 18 '13 at 19:52
  • You bet. Sorry there's no simple fix for this problem! – TotoroTotoro Dec 18 '13 at 19:52