【发布时间】:2013-12-26 15:24:30
【问题描述】:
我已经构建了一个几乎完成的 iOS 应用程序,但是,我最近经历了由于“内存压力”而导致它在一段时间后崩溃。所以我开始在 Instruments 中分析内存分配,并且确定,该应用确实使用了相当多的内存,而且它似乎只会在使用过程中增加。
但是,对于 Instruments 内存分配来说,我不太清楚 52% 的分配是在哪里进行的,如下面的屏幕截图所示:
这显然与核心动画有关,但我很难确定到底是什么,所以我认为那里的一些聪明人可能知道答案。
面包屑:
当在视图控制器之间移动时,我的应用使用自定义转场,其中会发生大量动画。这是一个例子:
@interface AreaToKeyFiguresSegue : UIStoryboardSegue
@end
...
@implementation AreaToKeyFiguresSegue
- (void)perform
{
[self sourceControllerOut];
}
- (void)sourceControllerOut
{
AreaChooserViewController *sourceViewController = (AreaChooserViewController *) [self sourceViewController];
KeyFigureViewController *destinationController = (KeyFigureViewController *) [self destinationViewController];
double ratio = 22.0/sourceViewController.titleLabel.font.pointSize;
sourceViewController.titleLabel.adjustsFontSizeToFitWidth = YES;
[UIView animateWithDuration:TRANSITION_DURATION delay:0 options:UIViewAnimationOptionCurveEaseIn animations:^{
// Animate areaChooser
sourceViewController.areaChooserScrollView.alpha = 0;
sourceViewController.areaScrollViewVerticalSpaceConstraint.constant = -300;
sourceViewController.backButtonVerticalConstraint.constant = 20;
sourceViewController.backButton.transform = CGAffineTransformScale(sourceViewController.backButton.transform, ratio, ratio);
sourceViewController.backButton.titleLabel.textColor = [UIColor redKombitColor];
sourceViewController.backArrowPlaceholderVerticalConstraint.constant = 14;
sourceViewController.backArrowPlaceholder.alpha = 1;
sourceViewController.areaLabelVerticalConstraint.constant = 50;
sourceViewController.areaLabel.alpha = 1;
[sourceViewController.view layoutIfNeeded];
} completion:^(BOOL finished) {
[destinationController view]; // Make sure destionation view is initialized before animating it
[sourceViewController.navigationController pushViewController:destinationController animated:NO]; // Push new viewController without animating it
[self destinationControllerIn]; // Now animate destination controller
}];
}
- (void)destinationControllerIn
{
AreaChooserViewController *sourceViewController = (AreaChooserViewController *) [self sourceViewController];
KeyFigureViewController *destinationController = (KeyFigureViewController *) [self destinationViewController];
destinationController.keyFigureTableViewVerticalConstraint.constant = 600;
destinationController.keyFigureTableView.alpha = 0.0;
destinationController.allFavoritesSegmentedControl.alpha = 0.0;
[destinationController.view layoutIfNeeded];
[sourceViewController.segueProgress setHidden:YES];
}
@end
每当要弹出视图控制器时,我都会做相反的事情:
- (IBAction)goBack:(id)sender
{
[UIView animateWithDuration:TRANSITION_DURATION delay:0 options:UIViewAnimationOptionCurveEaseIn animations:^{
[self.keyFigureTableView setAlpha:0];
self.keyFigureTableViewVerticalConstraint.constant = 700;
[self.allFavoritesSegmentedControl setAlpha:0];
[self.view layoutIfNeeded];
} completion:^(BOOL finished) {
[self.navigationController popViewControllerAnimated:NO]; // Pop viewController without animating it
}];
}
编辑:
大部分内存分配发生在推送视图控制器时,即使它之前已经显示过。 IE。从
A -> B -> C
B
B -> C
其中“->”=push,“”分配更多内存,“
更多详情
根据 Instruments,我没有僵尸并且没有泄漏。静态分析也没有给出任何结果。我的应用一直在分配内存,直到它最终崩溃。
我大约 70% 的内存分配发生在以下调用堆栈中,这与我的代码无关(反向调用树):
【问题讨论】:
-
使用“标记生成”按钮。在标尺上选择一个点,然后单击标记生成。然后选择右边的下一个点并再次单击标记生成,重复。 Instruments 将向您展示代际之间的差异——创建了哪些对象。
-
我唯一能从中得到的是一堆十六进制地址,而调用者总是
vm_allocate。 -
您可以查看扩展详细信息面板以查看堆栈。您发布的图像不是很清晰,我几乎看不到那里有什么,但是如果我理解正确,Core Animation 会为视图的后备存储分配内存以在那里绘制一些东西。你有定义了drawRect的自定义视图吗?如果你注释掉 layoutIfNeeded 会发生什么?
-
扩展细节基本上给出了与上述调用树相同的概述。如果我注释掉
layoutIfNeeded,则基本上没有动画。 -
那么你在你的布局代码中做了什么,可以post code sn-p吗?
标签: ios memory-management instruments