iOS ARC - 为什么对象不立即释放?

标签 ios iphone uiview automatic-ref-counting

也许这不是一个重复的问题,因为我已经搜索并尝试了很多关于如何在 ARC 下释放对象的解决方案。
代码很简单:

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    [self recreateView];

    UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapped:)];
    [self.view addGestureRecognizer:tap];
}

- (void)tapped:(UITapGestureRecognizer *)g
{
    [self recreateView];
}

- (void)recreateView
{
    @autoreleasepool {
        for (UIView *v in self.view.subviews) {
            [v removeFromSuperview];
        }
        MyView *vv = [[MyView alloc] initWithFrame:self.view.bounds];
        [self.view addSubview:vv];
    }
    [self _performHeavyWork];
}

- (void)_performHeavyWork
{
    int j = 0;
    for (int i = 0 ; i < 100000000; ++i) {
        j += random() % 7;
        j = j % 18747;
    }

}
@end

ViewController 只需添加一个点击手势识别器,其操作是在添加新 subview 之前删除旧 subview 。 MyViewUIView 的子类,它仅在释放时记录一条消息。

@implementation MyView
- (void)dealloc
{
    NSLog(@"dealloc");
}
@end

唯一的魔力是每次创建新 View 时都会调用-_performHeavyWork。当您持续快速点击屏幕时,ViewController 将忙于创建和丢弃 View 。然而,奇怪的是,所有被丢弃的 View 并不是立即释放,而是在你停止点击一段时间后释放。
这是该过程的概况: Allocation Profile

正如您所看到的,如果您继续点击,并且同时存在如此多的 MyView 实例,则内存会不断增长。如果你注释掉[self _performHeavyWork];,一切都会恢复正常。所以我的问题是:

  1. 为什么会发生这种情况?
  2. 我该如何解决这个问题?

最佳答案

我认为主要问题是您在主线程上执行繁重的工作。如果你把困难的东西放在不同的线程(或 GCD)上,你可能会看到你所期望的。

以下是对正在发生的事情的一些猜测。

iOS 仅在主线程上响应 UI 中的更改。因此,如果您将主线程用于其他用途,则水龙头会排队等待稍后处理。

您点击屏幕,主线程开始处理您的繁重工作。

您再次点击屏幕。 iOS 无法处理您的请求,因此会将事件排队。

最终您的繁重工作完成并将控制权返回给 iOS。

iOS 获取事件队列并在单个运行循环中处理它们,这意味着主循环自动释放池永远不会耗尽。

但是手动自动释放池呢?好吧,所有与 UI 相关的事情都发生在主循环和主线程上,因此在控制权返回到操作系统之前,removeFrmSuperview: 不会发生。在此之前, View 层次结构仍然保留对 View 的引用,因此内存会增长。

关于iOS ARC - 为什么对象不立即释放?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27666325/

相关文章:

ios - SDWebImage 使用 UIGraphicsBeginImageContextWithOptions 调整大小

ios - 如何将数据转换成小端格式?

jquery - iphone safari webkit 与 mac safari 的区别

ios - 如何调整所有屏幕尺寸的 View ?

ios - 单击按钮时的动画 View

ios - 添加了 SplitViewController 并且线程永远不会到达 viewDidLoad

ios - 如何设置 "if there is text in text view"

iphone - 模拟器、设备和应用商店的行为测试有什么区别

iphone - 如何从单独的类更改 UIWindow 的颜色?

ios - 圆形 CAGradientLayer mask