如何实现 didReceiveMemoryWarning?
Posted
技术标签:
【中文标题】如何实现 didReceiveMemoryWarning?【英文标题】:How to implement didReceiveMemoryWarning? 【发布时间】:2011-01-26 16:58:41 【问题描述】:我开发了一个简单的位置感知 iPhone 应用程序,除了手机内存不足的情况外,它的功能非常符合我们的预期。
在手机内存不足的情况下,我的应用程序会崩溃,如果我通过释放一些空间来增加手机内存,它会再次开始正常运行而不会崩溃。
当我对这个问题进行一些谷歌搜索时,我发现在内存不足的情况下,操作系统会将 didReceiveMemoryWarning 发送到当前层次结构中的所有控制器,以便每个控制器都应该实现 didReceiveMemoryWarning 方法并将 iboutlet 设置为 nil当前不可见的视图。
我还在某处读到,如果该控制器的视图不可见,则将调用带有 nil 参数的方法 setView 并且如果有一些出口变量附加到视图,则删除时会出现问题他们。
因此,有了所有这些基础,通过实现 didReceiveMemoryWarning 和 viewDidUnload 方法来处理 Iphone 引发的低级内存状况的最佳方法是什么。
如果可能,请给出适当的示例或链接以解决上述问题。
谢谢。
【问题讨论】:
***.com/questions/491075/… 【参考方案1】:我发布的一个示例...我从某处复制的...它可能会给您一些想法...
- (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];
【讨论】:
嘿 mihir 我有 iboutlets,我正在从 nib 文件加载我的视图,只需检查我的问题的评论。这是令人困惑的,因为视图不可见,然后它会调用 viewDidUnaload 那么我应该怎么做才能使 didReceiveMemoryWarning 或 viewDidUNload 或 setView 中的值无效??????? 但是对于每个视图都会有单独的 didReceiveMemoryWarning 函数,因此针对特定视图实现此方法...在 viewDidUnload 方法中使用相应的访问器方法将对象的值设置为 nil... 嗨,你确定 [super didReceiveMemoryWarning];释放对象后需要放 在 didReceiveWarning 中释放内存/资源只是答案的一半。你什么时候/在哪里重新创建它们?它是如何工作的?【参考方案2】:内存警告是向您发出的信号,表明您应该处置所有并非绝对重要的资源。大多数控制器将挂在数据缓存、中间数据或其他零碎的数据上,通常是为了节省重新计算。当他们收到内存警告时,他们应该开始刷新他们不需要立即操作的任何东西。
您如何确定什么是“关键”完全取决于您的应用程序的设计。例如,一个 OpenGL 游戏可以确定当前屏幕上的纹理是有价值的,并刷新不可见的纹理,或当前游戏区域边界之外的关卡数据。具有大量会话日志的应用程序(例如 IRC 客户端)可能会将它们从内存中刷新到磁盘上。
正如您所观察到的,警告会发送到层次结构中的每个控制器,因此每个部分都需要单独确定哪些数据构成“对操作至关重要”,哪些数据构成“消耗性”。如果您已经对它们进行了优化并且仍然收到内存不足的警告,那么很遗憾,是时候重新审视您的核心应用程序设计了,因为您已经超出了硬件的限制。
【讨论】:
好的,我已经通过在我的 viewDidUnload 方法中将 outlet 设为 nil 来制定我的解决方案。【参考方案3】:在 ios 5 及更早版本上。
当控制器收到内存警告时,didReceiveMemoryWarning 将被调用。此时,如果控制器的视图不在视图层次结构中,则视图将被设置为 nil 并自动调用 viewDidUnload。所以我们在 viewDidUnload 中要做的就是释放在 viewDidLoad 中创建的或者从 Nib 中创建的子视图。像这样:
- (void)viewDidUnload
self.subView = nil;
self.subViewFromNib = nil;
- (void)didReceiveMemoryWarning
self.someDataCanBeRecreatedEasily = nil;
[super didReceiveMemoryWarning];
在 iOS6 上。
控制器在收到内存警告时不会自动释放视图。所以 viewDidUnload 永远不会被调用。 但是当内存警告发生时,我们仍然需要释放我们的视图(包括子视图)。 像这样。
- (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]。导致如果视图未加载,此方法将自动加载视图。
请注意,我们可以在视图没有添加到窗口时释放视图。
【讨论】:
实际上你可能想检查if (![self isViewLoaded] || [self.view window] == nil)
。无论哪种情况,您都想清理子视图和其他内容。【参考方案4】:
您可以决定在didReceiveMemoryWarning
中做什么。操作系统告诉您内存不足,您需要尽快释放内存。这个想法是你应该释放所有缓存的数据,卸载不可见的视图,等等。细节是特定于应用程序的。
【讨论】:
【参考方案5】:您还可以释放didReceiveMemoryWarning
中为类中的静态变量分配的内存。因为一旦为静态变量分配了内存,它就不会在应用程序运行期间被释放。
【讨论】:
这个页面上有一小段“内存警告”:developer.apple.com/iphone/library/documentation/Cocoa/… 这几天没有找到任何其他链接而不是那个【参考方案6】:令我惊讶的是,官方 iPhone 示例中只有少数应用程序实现了didReciveMemoryWarning
。您可以使用 iPhoneCoreDataRecipes 示例作为参考。
一些示例(例如 TableViewSuite)甚至可以做其他事情 ;-)
【讨论】:
以上是关于如何实现 didReceiveMemoryWarning?的主要内容,如果未能解决你的问题,请参考以下文章
如何在OpenGL应用程序中响应didReceiveMemoryWarning
iOS:didReceiveMemoryWarning 的帮助:
didReceiveMemoryWarning、viewDidUnload 和 dealloc
iOS 6 中的 didReceiveMemoryWarning