如何实现didReceiveMemoryWarning?

我已经开发了一个简单的位置感知的iPhone应用程序,除了在手机的低内存条件下,function上我们的期望非常好。

在手机内存不足的情况下,我的应用程序崩溃,如果我通过释放一些空间来增加手机内存,它再次开始工作,没有任何崩溃。

当我做了一些关于这个问题的search时,我发现在内存不足的情况下,操作系统会发送didReceiveMemoryWarning给当前层次结构中的所有控制器,以使它们中的每一个都应该实现didReceiveMemoryWarning方法,并且将iboutlet设置为nil目前不可见。

我也读过的地方,如果该控制器的视图不可见的方法setView与nil参数将被调用,如果有一些socketsvariables附加到视图将有问题,在删除它们。

所有这些基金会通过实施didReceiveMemoryWarningviewDidUnload方法来处理Iphone提出的低级内存条件是最好的。

请给出一个适当的例子或链接,如果可能的话解决上述问题。

谢谢。

我发布的一个例子…我已经从somwhere复制…它可能会给你一些想法…

- (void)didReceiveMemoryWarning { // Release anything that's not essential, such as cached data (meaning // instance variables, and what else...?) // Obviously can't access local variables such as defined in method // loadView, so can't release them here We can set some instance variables // as nil, rather than call the release method on them, if we have defined // setters that retain nil and release their old values (such as through use // of @synthesize). This can be a better approach than using the release // method, because this prevents a variable from pointing to random remnant // data. Note in contrast, that setting a variable directly (using "=" and // not using the setter), would result in a memory leak. self.myStringB = nil; self.myStringD = nil; [myStringA release];// No setter defined - must release it this way [myStringC release];// No setter defined - must release it this way /* 3. MUST CONFIRM: NOT necessary to release outlets here - See override of setView instead. self.labelA = nil; self.imageViewA = nil; self.subViewA = nil; */ // Releases the view if it doesn't have a superview [super didReceiveMemoryWarning]; } 

内存警告是一个信号给你,你应该处理任何不是绝对关键的资源。 大多数控制器将挂在数据caching,中间数据或其他零碎上,通常用于保存重新计算。 当他们收到记忆警告时,他们应该开始冲洗任何他们不需要的东西来操作。

你如何确定什么是“关键”完全取决于你的应用程序的devise。 例如,OpenGL游戏可以确定当前在屏幕上的纹理是有价值的,并且是不可见的齐平纹理,或者在当前游戏区域的边界之外的等级数据。 具有大量会话日志的应用程序(如IRC客户端)可能会将其从内存和磁盘中清除。

正如你所观察到的那样,这个警告被发送给你的层次结构中的每个控制器,因此每一个部分都需要分别确定哪些数据构成“对操作至关重要”,什么构成“可消耗”。 如果你已经对它们进行了优化,并且仍然出现了内存不足的警告,那么很遗憾,重新审视核心应用程序devise的时间已经到了,因为你已经超出了硬件的限制。

在iOS 5和更早版本上。

当控制器收到内存警告时,将会调用didReceiveMemoryWarning。 那时,如果控制器的视图不在视图层次结构中,视图将被设置为nil,并且viewDidUnload将被自动调用。 所以我们必须在viewDidUnload中做的事情是释放在viewDidLoad中创build的子视图或从Nib创build的子视图。 喜欢这个:

 - (void)viewDidUnload { self.subView = nil; self.subViewFromNib = nil; } - (void)didReceiveMemoryWarning { self.someDataCanBeRecreatedEasily = nil; [super didReceiveMemoryWarning]; } 

在iOS6上。

接收到内存警告时,控制器不会自动释放视图。 所以viewDidUnload永远不会被调用。 但是当memry警告发生时,我们仍然需要释放我们的视图(包括子视图)。 喜欢这个。

 - (void)didReceiveMemoryWarning { if ([self isViewLoaded] && [self.view window] == nil) { self.view = nil; self.subView = nil; self.subViewFromNib = nil; } self.someDataCanBeRecreatedEasily = nil; [super didReceiveMemoryWarning]; } 

请注意,在我们知道加载视图之前,我们不会调用[self view]。 导致该方法将自动加载视图如果视图没有加载。

请注意,只有当视图未添加到窗口时,我们才能释放视图。

didReceiveMemoryWarning要做什么决定由您决定。 操作系统告诉你内存不足,你需要尽可能快地释放内存。 这个想法是,你应该释放任何caching的数据,卸载不可见的视图等。细节是特定于应用程序的。

您也可以在didReceiveMemoryWarning释放内存,您在类中为静态variables分配内存。 因为一旦分配了静态variables的内存,它就不会在应用程序运行期间被释放。

令我惊讶的是,官方iPhone示例中只有几个应用程序实现了didReciveMemoryWarning 。 您可以使用iPhoneCoreDataRecipes示例作为参考。

一些样本(例如TableViewSuite)甚至做了别的事情;-)