我应该在didReceiveMemoryWarning之后以什么方法重新创建资源?

时间:2013-05-31 10:01:48

标签: iphone ios memory-management uiviewcontroller

我有一个具有私有NSArray变量的视图控制器。变量在viewDidLoad方法中初始化。调用didReceiveMemoryWarning时会出现一些问题:

  1. 我应该将私有变量设置为nil吗?
  2. 如果我将它设置为nil,必须重新创建哪种方法?视图控制器是否调用viewDidLoad方法来重新创建它?
  3. 我问,因为视图的其他方法需要此变量,如果它是nil则无法工作。

    谢谢!

5 个答案:

答案 0 :(得分:4)

通常,您可以通过设置器(例如nil)分配self.propertyName = nil来卸载私有属性。或者你可以在调用release之后将ivar设置为nil,例如[_propertyName release]; _propertyName = nil;,但前者更可取。

当内存不足时调用didReceiveMemoryWarning方法。它在每个视图控制器上调用,包括负责当前可见UI的一个(

因此,当您调用didReceiveMemoryWarning时,您不能随意卸载数据 - 视图控制器可能需要该数据,如果它当前在显示器上可见。

一般原则是didReceiveMemoryWarning可以摆脱它可以帮助释放内存的任何资源,但只有那些不是立即需要的资源。例如,在OpenGL游戏中,您不会卸载当前在显示器上可见的纹理。但是,请参阅我的最后一段。

通常,您需要在需要时检查它们是否已加载来重新加载资源,如果没有,则加载它们。

不值得利用/释放微小资源,例如单个正常大小的字符串。你应该专注于占用大量记忆的物品。

幕后内存管理的最新进展意味着您现在不太可能需要实际卸载数据 - 操作系统可以在后台卸载和重新加载未压缩的图像数据等。

正如Hot Licks所提到的,模拟器有一个模拟内存警告的选项。值得在应用程序的各个点触发此内存警告以查看其行为。

答案 1 :(得分:1)

创建懒惰加载数据的自定义getter。像这个片段这样的东西对于非多线程的解除是有益的:

- (NSArray*) dataArray {
  if(_dataArray) return _dataArray;

  _dataArray = [self lordata];
  return _dataArray;
}

这样,如果您在内存警告中“释放”数据,则始终会重新加载数据

答案 2 :(得分:0)

初始化ViewController时,ViewDidLoad方法只调用一次。如果必须将一些数据重新加载到NSArray,则应该在需要时调用自己的方法来执行此操作。

如果代码的各个部分使用了这个数组,那么你应该考虑重新设计你的代码结构,以避免仅在一个对象中集中大量数据。

编辑:正如@occulus在下面的评论中指出的那样,在View初始化时不会调用它,但是ViewController加载View时我的错误

答案 3 :(得分:0)

作为一个例子,我有一个应用程序将数据下载到一个非常长的表视图(可能是1000个记录)。为了支持这一点,我实现了一个“稀疏”数组,允许在引用时通过网络“故障”的空元素(在下载时在表格单元格中使用“下载”指示符)。

这是被操纵的,因此当didReceiveMemoryWarning发生时,将使用最近最少使用的算法清除数组,以删除最旧的N%数组。恢复将是自动的 - 清空的单元格在被引用时会重新加载。

不是我推荐这个特定的方案,而是注意拥有大量数据的一般特征,有一种方法可以“优先”应该删除的内容,并且有一种“软”方式来重新加载数据(理想情况下只重新加载在不久的将来需要的部分)。

答案 4 :(得分:-2)

最好将变量设置为nil。我的意思是释放它在didReceiveMemoryWarning中保存的内存并设置脏标志。

您可以随时检查数组getter中的脏标志(您可以自己编写)并重新填充它。这可能不是最好的方式。这完全取决于阵列的用法。