serge-k
serge-k

Reputation: 3512

Memory Accumilation, switching between UIViewControllers, what is ok?

Thanks in advance for your time!

Xcode Version 5.1.1 for iOS 7+ applications, ARC enabled.

I am researching the best pattern for switching between multiple UIViewControllers without using a UINavigationController or a UITabBarController; best being with respect to memory allocation and release. I am staying away from navigation and tab bar because they use their own navigation objects and take up real estate on the screen.

For the sake of testing I made two test projects. With two UIViewControllers, two UIButtons and two UILabels...

1) Uses a triggered segue that was set up by CTRL-dragging a UIButton to the next UIViewController and selecting "modal". And to return, a UIButton's Touch Up Inside IBAction is used to dismiss the second UIViewController, i.e.

- (IBAction)pressedButtonGoToTwo:(UIButton *)sender
{
    [self dismissViewControllerAnimated:true completion:nil];
}

2) Uses a transitional view controller described in this SO post: Animate change of view controllers without using navigation controller stack, subviews or modal controllers? (thanks to all who contributed). To go to the second UIViewController a UIButton's Touch Up Inside IBAction is used, i.e.

- (IBAction)pressedButtonGoToOne:(UIButton *)sender
   {
        UIStoryboard *mainStoryBoard = [UIStoryboard storyboardWithName:@"Main"    bundle:nil];
        TBAViewController *vc2 = [mainStoryBoard instantiateViewControllerWithIdentifier:@"TBAViewController2"];
        TBAAppDelegate *tbaAppDelegate = [UIApplication sharedApplication].delegate;
        [tbaAppDelegate.transitionController transitionToViewController:vc2 withOptions:UIViewAnimationOptionTransitionFlipFromBottom];
   }

And to return, a UIButton's Touch Up Inside IBAction is used on the second UIViewController, i.e.

- (IBAction)pressedButtonGoToOne:(UIButton *)sender
   {
        UIStoryboard *mainStoryBoard = [UIStoryboard storyboardWithName:@"Main"    bundle:nil];
        TBAViewController2 *vc1 = [mainStoryBoard instantiateViewControllerWithIdentifier:@"TBAViewController"];
        TBAAppDelegate *tbaAppDelegate = [UIApplication sharedApplication].delegate;
        [tbaAppDelegate.transitionController transitionToViewController:vc1 withOptions:UIViewAnimationOptionTransitionFlipFromBottom];
   }

A TransitionController UIViewController type class is defined in the project.

--

I understand there are countless ways of doing this, e.g. unwind UIViewController. But these are two ways I am most familiar with.

Instruments Allocations analysis was used to make the following plots of memory allocation and release profiles using an actual iPhone 4 (not simulator).

1) The net change of 11.96kB was noted after 12 transitions from the first to the second UIViewController.

2) The net change of 54.66kB was noted after 6 transitions from the first to the second UIViewController (realized there were only 6 at time of post, because after switching to the second UIViewController the allocated memory for the first is released).

enter image description here

--

My interpretation of the plots is that both approaches work reasonably well, however none of them result in a net zero memory allocation change.

(1) shows that the first UIViewController is always allocated and the second UIViewController is allocated and dismissed.

(2) shows that the transitional UIViewController is allocated for each transition between either the first or second UIViewControllers. However, whenever either are allocated the transitional UIViewController is dismissed, i.e. the memory profile looks like a step up and immediately down, not like in (1), where the step up lasts until the second UIViewController is dismissed.

The tests were performed on an actual iPhone, so a Memory Warning was not captured on the plots. However, on a simulator when the Memory Warning is triggered, some additional memory is released but it never gets back to the baseline.

--

My questions specifically...

Q1) Are these results acceptable?

Q2) Is a net zero memory change not achievable in the real world? If so, then what is an acceptable amount of memory leaked for an actual app with lots of objects per UIViewController? 100kB, 200kB...?

Q3) What design pattern should I be using? Are there others? More efficient?

Thanks again guys.

Upvotes: 0

Views: 388

Answers (1)

Matt S.
Matt S.

Reputation: 1892

An intriguing problem. Here are some thoughts:

1) Looks like you're using a storyboard. Storyboards are strange beasts in the iOS ecosystem. They are like nibs, but appear to have additional caching logic in place beyond the norm. I would attempt to reproduce your results without using a storyboard and see what you get.

2) The second version with the transition controller makes sense you'd take up more memory because you now have an additional view controller in play beyond the original two, so that will take up extra memory.

Overall you're going to have some memory growth in the application as the OS builds out its caches, along with the runtime caching things for you. Depending on the size of the application, you might have 50k or 5000k memory growth. In this particular scenario, I would see 15-30k worth of growth being acceptable.

Upvotes: 1

Related Questions