内存累积,View Controller 之间切换,怎么回事?

Posted

技术标签:

【中文标题】内存累积,View Controller 之间切换,怎么回事?【英文标题】:Memory Accumilation, switching between UIViewControllers, what is ok? 【发布时间】:2014-09-08 23:56:57 【问题描述】:

提前感谢您的宝贵时间!

适用于 ios 7+ 应用程序的 Xcode 版本 5.1.1,已启用 ARC。

我正在研究在不使用 UINavigationController 或 UITabBarController 的情况下在多个 UIViewController 之间切换的最佳模式;最好是关于内存分配和释放。我远离导航和标签栏,因为它们使用自己的导航对象并占用屏幕上的空间。

为了测试,我做了两个测试项目。有两个 UIViewControllers、两个 UIButtons 和两个 UILabels...

1) 使用通过按住 CTRL 键将 UIButton 拖到下一个 UIViewController 并选择“模态”来设置的触发转场。并返回,UIButton 的 Touch Up Inside IBAction 用于关闭第二个 UIViewController,即

- (IBAction)pressedButtonGoToTwo:(UIButton *)sender

    [self dismissViewControllerAnimated:true completion:nil];

2) 使用此 SO 帖子中描述的过渡视图控制器:Animate change of view controllers without using navigation controller stack, subviews or modal controllers?(感谢所有贡献者)。要转到第二个 UIViewController,使用了 UIButton 的 Touch Up Inside IBAction,即

- (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];
   

然后返回,在第二个 UIViewController 上使用 UIButton 的 Touch Up Inside IBAction,即

- (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];
   

项目中定义了一个TransitionController UIViewController 类型类。

--

我知道有无数种方法可以做到这一点,例如展开 UIViewController。但这是我最熟悉的两种方式。

仪器分配分析用于使用实际 iPhone 4(不是模拟器)绘制以下内存分配和释放配置文件。

1) 从第一个 UIViewController 到第二个 UIViewController 的 12 次转换后,净变化 11.96kB。

2) 从第一个 UIViewController 到第二个 UIViewController 的 6 次转换后,注意到 54.66kB 的净变化(在发布时意识到只有 6 个,因为在切换到第二个 UIViewController 后,为第一个分配的内存被释放) .

--

我对图表的解释是,这两种方法都运行得相当好,但是它们都不会导致净零内存分配变化。

(1) 显示第一个 UIViewController 始终被分配,第二个 UIViewController 被分配和关闭。

(2) 显示过渡 UIViewController 是为第一个或第二个 UIViewController 之间的每个过渡分配的。但是,每当分配任何一个时,过渡 UIViewController 都会被解除,即内存配置文件看起来像一个向上和立即向下的步骤,而不像在 (1) 中,向上一直持续到第二个 UIViewController 被解除。

测试是在真实的 iPhone 上执行的,因此图中未捕获内存警告。但是,在模拟器上,当触发内存警告时,会释放一些额外的内存,但它永远不会回到基线。

--

我的问题具体...

Q1) 这些结果是否可以接受?

Q2) 在现实世界中是否无法实现净零内存变化?如果是这样,那么对于每个 UIViewController 有很多对象的实际应用程序来说,可接受的内存泄漏量是多少? 100kB、200kB...?

Q3) 我应该使用什么设计模式?还有其他人吗?效率更高?

再次感谢各位。

【问题讨论】:

【参考方案1】:

一个有趣的问题。以下是一些想法:

1) 看起来您正在使用情节提要。故事板是 iOS 生态系统中的奇葩。它们就像笔尖,但似乎有超出规范的额外缓存逻辑。我会尝试在不使用情节提要的情况下重现您的结果,然后看看您会得到什么。

2) 带有过渡控制器的第二个版本会占用更多内存,因为除了原来的两个之外,您现在还有一个额外的视图控制器在运行,因此会占用额外的内存。

总体而言,随着操作系统构建其缓存以及运行时为您缓存的内容,您将在应用程序中获得一些内存增长。根据应用程序的大小,您可能会有 50k 或 5000k 的内存增长。在这种特殊情况下,我认为 15-30k 的增长是可以接受的。

【讨论】:

谢谢!如果时间允许,我肯定会在本周晚些时候在没有 Storyboard 的情况下运行更多测试。我确实喜欢 (2) 的内存配置文件,它从不在内存中将两个 UIViewController 堆叠在一起。

以上是关于内存累积,View Controller 之间切换,怎么回事?的主要内容,如果未能解决你的问题,请参考以下文章

iOS - 内存警告会卸载 View Controller 并使应用程序无响应

ASP.NET MVC中Controller与View之间的数据传递

Asp.net MVC中 Controller 与 View之间的数据传递

iPad View Controller 内存管理

在 Modal View Controller 中使用 UINavigationController 进行内存管理

无法在 View Controller 和 Model 之间传递数据