奇怪的 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 允许应用程序正确地销毁与先前销毁的视图的所有联系。
我有一个正在开发的应用程序,我很难理解为什么 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 允许应用程序正确地销毁与先前销毁的视图的所有联系。