奇怪的 ARC 内存释放问题

Strange ARC Memory Release Issue

我有一个正在开发的应用程序,我很难理解为什么 Xcode 似乎在告诉我它正在坚持(看起来)几乎所有创建的东西,时不时地造成一些内存压力..

到目前为止,我都相当简单地介绍了我的所有观点、信息等。我有 2 个 ViewController,一个在启动时出现,另一个在登录成功后出现。

显示的其余信息由我创建的各种子class处理(其中大部分是 UIView、[=16 的子class =],或 UIButton)。

我经常使用的一个 class 称为 MenuView,它实际上是一个 class,它创建...一个菜单。

- (MenuView *)createMenuWithFrame:<FRAME> size:<SIZE> type:<TYPE> view:<VIEW>{
    MenuView *menu = [MenuView alloc] initWithFrame:<FRAME>];
    /// Code for creating a UIView with a background image for a menu.
    ...
    /// Done. Now the menu gets added to the passed view <VIEW>. 
    return menu;
}

我的问题似乎在我呈现的每个视图中都存在,因为实际上现在每个添加到层次结构(显示)的视图都是 MenuView,或使用菜单。

示例

我非常简单地呈现视图,调用初始化子classes。

让我们以我的设置视图子class SettingsView为例。

HomeViewController.m,如上所述,查看控制器 #2。

#pragma mark Settings
- (IBAction)openSettings:(id)sender {
    [SettingsView createSettingsViewForView:self.view];
}

SettingsView.m注意: 在我的 MenuView.m class 中,我将创建的菜单添加到我传递给它的 UIView .

#import "SettingsView.h"

UIView *screenView;

@implementation SettingsView  // a UIView subclass type in interface (.h)

#pragma mark - Create View
+ (void)createSettingsViewForView:(UIView *)view {
    // Here I create a MenuView. This method is just a wrapper of 
    // the menu class. It doesn't create a SettingsView, but rather 
    // creates another MenuView *menu.

    // The menu is given some content, then "shown" (alpha 0 -> 1) 
    // through the MenuView class by using [menu animateMenu:menu];
}

我知道频繁使用图像会 "expensive" 在内存分配方面,但我很确定如果处理得当,它仍然应该被释放(从使用的内存中删除)。就我而言,我认为我处理得当,现在仍然这么认为..

关闭 ANY MenuView 项目后,我将菜单设置为动画(alpha),然后在完成动画后,将菜单从超级视图中删除。

- (void)closeMenuView:(UIButton *)closeButton {
    MenuView *menu = (MenuView *)closeButton.superview;
    [UIView animateWithDuration:0.1 delay:0 options:UIViewAnimationOptionCurveEaseOut | UIViewAnimationOptionAllowUserInteraction animations:^{
        <CUSTOM TRANSITION OUT OF VIEW>
    } completion:^(BOOL finished) {
        [menu removeFromSuperview];
    }];
}

问题

当我从 HomeViewController.m 显示设置视图时,我的内存(已经高于我想要的)峰值 ~10 MB 。 我知道根据屏幕尺寸/分辨率优化图像尺寸会大大减少一些内存使用,但这与我遇到的问题无关。

添加 ~10 MB 后,从 88 MB 到 98 MB,关闭菜单没有任何效果在Xcode的眼里。

使用Instruments,我发现打开菜单,然后关闭菜单实际上会降低持久内存的使用,这也是应该的(~打开设置时 11 MB + 1.5 MB.

另一个让我怀疑我的 "removing" 视图方法的令人不安的问题是,当我显示和删除一个更大(更复杂)的菜单时,一个叫做 MailView,内存每次视图为 "opened" 时都会爬升,但不会释放任何内存,因此它会继续增长。 Instruments 告诉我没有内存泄漏,但显然存在保留此内存的问题。

这是通过仪器进行录音的截图。这是从`Details -> Statistics -> Allocation Summary(搜索 "Mail")-> MailView.

无论出于何种原因,我的应用程序似乎都在继续创建 MailView 而没有销毁它们。


问题

我的问题是(感谢您一直陪在我身边),这是 Xcode and/or 仪器在读取我的内存使用情况时出现的错误吗?或者这是应用程序的内部问题。我知道我可能需要提供更多信息才能获得最佳答案,但从我展示和解释的内容来看,每个视图只是一个 UIView,它被添加到视图层次结构中,然后被删除(随后 "killing" 链接在下方视图中的任何子视图)。

SO 上有很多关于类似问题的帖子,但很多帖子建议我在做什么(removeFromSuperview,= nil(我试过),使用 Instruments,手动 dealloc,尽管我使用的是 ARC)。

如果有人知道我遗漏了什么,或者根本不知道,请告诉我,我将不胜感激。谢谢

仅供参考

我知道 iOS 设备似乎基本上保留了它可以保留的所有内容,除非它 A) 认为您不再需要它(很可能是超时)或 B) 有内存压力,所以它摆脱了 "least important" 项。但同样,情况似乎并非如此,因为我遇到的这些问题有时会收到内存警告。

更新:

(我今天刚刚更新到 8.2.1,所以我现在可以通过 Xcode 中的 DMG 查看回溯(在方案中启用了 Malloc),而不必通过 Instruments)

这是在选择 MailView 项目中的 一个 时的结构片段。这是在我打开和关闭邮件 2 次之后,因此它保留了 2 个视图。这是我需要解决的问题。

这是另一个 运行 多次打开和关闭邮件视图的内存图的片段。

嗯.. 看来尽管我尽了最大的努力来销毁任何习俗 "views",但在销毁保留这些 "views" 的对象方面肯定是非常无效的在 运行 期间跨应用程序 VM 克隆和复制。

特别是,罪魁祸首不是别人,正是NSArray。对于正在创建的每个视图,都会生成并存储一个简单的数组 CUCells *cells 视图子视图(单元格)。我最初将子类设计为对其父类的强引用,但需要将其更改为在每次 "opened" 时独立创建。进行此更改后,每次打开视图时都会初始化和分配 cells,无法与 [cell removeFromSuperview] 一起销毁。

  • 此方法的简单覆盖以及 cells = nil 和其他 "strong" refs 允许应用程序正确地销毁与先前销毁的视图的所有联系。