gpt4 book ai didi

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

转载 作者:塔克拉玛干 更新时间:2023-11-02 10:02:39 24 4
gpt4 key购买 nike

也许这不是一个重复的问题,因为我搜索并尝试了很多关于如何在 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 并不是立即dealloc,而是在你停止点击一段时间后。
这是流程的简介: 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/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com