remove大量view时导致内存急剧增长该如何处理?

无敌鲨鱼炮
  • 448

这是遍历移除指定类型subview的方法:

- (void)refresh {
    for (UIView *view in self.subviews) {
        if ([view isMemberOfClass:[GoodListThemeView class]] || [view isMemberOfClass:[SingleGoodsThemeView class]]) {
            [view removeFromSuperview];
        }
    }
}

当调用此方法时,内存变化如下:

如果我将[view removeFromSuperview];这一句代码注释掉,则不会出现这种内存暴涨后又骤降的现象。

我猜测是那个for循环中产生了大量临时对象导致的,于是我使用autoreleaserpool:

- (void)refresh {
    for (UIView *view in self.subviews) {
        @autoreleasepool {
            if ([view isMemberOfClass:[GoodListThemeView class]] || [view isMemberOfClass:[SingleGoodsThemeView class]]) {
                [view removeFromSuperview];
            }
        }
    }
}

但是内存还是突然暴涨然后下降。

谁能提供一点思路。。。

回复
阅读 2.4k
6 个回答
  1. 需要@autoreleasepool的作用,它的真实作用是 如果在包裹语句中创建了临时变量,则可以提前释放,显然你使用情景并不符合这一原则,故无效
  2. for... in ...快速枚举原则上是不应该对集合中的元素作修改的,也许可以试试块遍历(但我觉得应该差不太多,for in见到用的例子也挺多的),for循环不考虑是因为会导致多出一份临时拷贝
  3. removeFromSuperview后并不代表这块内存就释放了,正确的说法是会在稍后的某个时间点释放(一般是下一次事件循环),如果要及时释放,可直接手动置空,view = nil;
桂一枫
  • 2
新手上路,请多包涵

既然你看到内存暴涨了,你有没有用 Instruments 看一下这个时间段的 Allocation trace?这段时间里有哪些对象被创建或者有哪些 malloc 发生?

我猜 for循环是removeFromSuperview方法是一个 异步耗时操作。 需要占内存比较大 , 想办法移除完成一个后在移除下一个。搞一个同步之类的。

Yueeeeee
  • 5
新手上路,请多包涵

[view.subviews makeObjectsPerformSelector:@selector(removeFromSuperview)];

托马斯_维德
  • 3
新手上路,请多包涵

改成阻塞去做,弃用循环,写一个迭代器函数并递归自身

兮文swifter
  • 4
新手上路,请多包涵

内存暴涨,我怀疑是removeFromSuperview方法延时生效造成的,可能在生效之前for循环在不断执行造成内存暴涨,解决方法还是手动置空吧

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
你知道吗?

宣传栏