Question

All,

I am running into some performance/memory issues when using several ChildViewControllers in my ParentViewController. Here is my situation: I have a ParentViewController with a dynamic number of ChildViewControllers - some times as many as 20. They are contained in a UIScrollView, and are paged through. I'm running into problems when I have several on the page (I'm only loading the first two, then building the others as I swipe), however, having that many within the ParentViewController is starting to cause some crashes due to memory.

The ChildViewController has a lot going on in it, and I'm going through it to make sure it's as efficient as possible, however, I have concerns about this approach working on older devices (as is, I'm getting crashes on the 5S).

It seems that it would help to change the view controllers to just be views, but it'd be a pretty large endeavor as the VC is complex. One suggestion I had was to create a view from the existing view controller's view, and set several delegate methods on the view and interact with the views from the ParentViewController that way. Does any one have any thoughts on the efficiency of that method as a opposed to the current method of using ChildViewControllers?

Another thought I had was to build a custom ContainerViewController and have all the children in there to swipe through, but I wasn't sure if that would give me an advantage over using the children in a UIScrollView.

Any thoughts?

Was it helpful?

Solution

I personally would not advocate the refactoring of your code to use views rather than view controllers. The view controller, itself, is unlikely to be the source of the memory problems, but rather the model objects they keep track of (as well as the assets the view controller's view uses). I think the key is to simply remove the view controllers (and their views) as they scroll off of the screen.

In your scrolling logic, as you're adding child view controllers that scroll into view, you are presumably doing all of the appropriate containment calls:

UIViewController *newChildViewController = ...
[self addChildViewController:newChildViewController];
newChildViewController.view.frame = ...; 
[self.scrollView addSubview:newChildViewController.view];
[newChildViewController didMoveToParentViewController:self];

(See WWDC 2011 video Implementing UIViewController Containment for a discussion about why it's important to do these containment calls, namely to keep your view controller hierarchy synchronized with your view hierarchy.)

As the child views scroll out of view, you just do the appropriate containment calls to remove the child controller (and its view):

[childViewControllerToRemove willMoveToParentViewController:nil];
[childViewControllerToRemove.view removeFromSuperview];
[childViewControllerToRemove removeFromParentViewController];
// also remove any other strong references you have to that childViewControllerToRemove

Alternatively, you might want to contemplate using a UIPageViewController which (in iOS 6+) offers scrolling page view (UIPageViewControllerTransitionStyleScroll) for the transitionStyle. This simplifies the amount of custom container code you have to write to handle the view controllers that scroll in and out of view. The UIPageViewController is designed precisely for this situation of scrolling (or paging) through a bunch of different view controllers' views. See the Page View Controllers discussion in the View Controller Catalog for iOS.

OTHER TIPS

I don't think moving them all to UIView's will help. You could achieve this same effect by just adding aChildViewController.view without ever technically adding it as a childView. I would optimize the loading of the views into your UIScrollView. Make sure you only have, say 4 views loaded into memory at any one time. Another option would be to use a horizontal UITableView or UICollectionView so you can reap the memory management features they have build in.

You could turn it into a tableview and let the cell dequeue take over. You would only have a few in memory at a time then.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top