如何管理静态、延迟加载的字典和数组的内存负载
一般来说,我使用静态数组和字典来包含类中的查找表。然而,随着课程数量迅速增加到数百个,我对是否继续使用这种模式犹豫不决。即使这些静态集合是延迟初始化的,当有人使用我的应用程序时,我基本上会发生有限的内存泄漏。
其中大多数是字符串数组,因此我可以将字符串转换为可与 switch 语句等一起使用的 NSInteger 常量。
我可以在每次调用时重新创建数组/字典,但其中许多函数被大量使用和/或紧密使用循环。
所以我试图想出一种既高效又不持久的模式。
如果我将信息存储在 plist 中,iphoneOS 在加载时是否会智能地缓存这些信息?
您还有其他可能相关的方法吗?
编辑 - 答案示例
基于下面提出的解决方案,这就是我将要使用的...
首先,通过类别向 NSObject 添加一个方法。
- (void)autoreleaseOnLowMemory;
现在,每当我想在辅助函数中创建延迟加载静态数组或字典时,我都可以使用以下模式...
- (id)someHelperFunction:(id)lookupKey {
static NSDictionary *someLookupDictionary = nil;
if (!someLookupDictionary) {
someLookupDictionary = [[NSDictionary dictionaryWithObjects:X, Y, Z, nil] autoreleaseOnLowMemory];
}
return [someLookupDictionary objectForKey:lookupKey];
}
现在,如果我们用完了,而不是静态字典一直存在到程序结束它将被释放,并且仅在再次需要时重新实例化。是的,在 iPhone 上运行的大型项目中,这可能很重要!
PS - autoreleaseOnLowMemory 的实现很简单。只需创建一个单例类,其中的方法接受一个对象并将其保留在集合中。让该单例监听内存不足警告,如果收到警告,则释放该集合中的所有对象。可能还想添加手动释放功能。
Generally, I use static arrays and dictionaries for containing lookup tables in my classes. However, with the number of classes creeping quickly into the hundreds, I'm hesitant to continue using this pattern. Even if these static collections are initialized lazily, I've essentially got a bounded memory leak going on as someone uses my app.
Most of these are arrays of strings so I can convert strings into NSInteger constants that can be used with switch statements, etc.
I could just recreate the array/dictionary on every call, but many of these functions are used heavily and/or in tight loops.
So I'm trying to come up with a pattern that is both performant and not persistent.
If I store the information in a plist, does the iphoneOS do anything intelligent about caching those when loaded?
Do you have another method that might be related?
EDIT - ANSWER EXAMPLE
Based on a solution proposed below, here's what I'm going to work with...
First, add a method to NSObject via category.
- (void)autoreleaseOnLowMemory;
Now, whenever I want to create lazy-loading static array or dictionary in a helper function, I can just use the following pattern...
- (id)someHelperFunction:(id)lookupKey {
static NSDictionary *someLookupDictionary = nil;
if (!someLookupDictionary) {
someLookupDictionary = [[NSDictionary dictionaryWithObjects:X, Y, Z, nil] autoreleaseOnLowMemory];
}
return [someLookupDictionary objectForKey:lookupKey];
}
Now, instead of that static dictionary living until the end of the program, if we're running out of memory it will be released, and only re-instantiated when needed again. And yes, in a large project running on an iphone, this can be important!
PS - The implementation of autoreleaseOnLowMemory is trivial. Just create a singleton class with a method that takes an object and retains it in a set. Have that singleton listen for low memory warnings, and if it gets one, release all the objects in that set. May want to add a manual release function as well.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我通常更喜欢 plist,因为它们很容易在不同的代码部分中维护和重用。如果从文件将它们加载到 NSDictionary 的速度是一个问题(并检查分析器以确保),您可以随时将它们放入一个实例变量中,当您收到内存警告时可以释放该实例变量。
I generally prefer plists for this just because they're easy to maintain and reuse in different sections of code. If the speed of loading them into an NSDictionary from file is a concern (and check the profiler to be sure) you can always put them into an instance variable which you can release when you get a memory warning.
如果您只处理字符串,则可以使用 C 数组。
如果您偶尔需要一个真正的 NSArray 或 NSDictionary:
plist 将涉及每个集合的磁盘命中和 xml 解析。据我所知,只有 NSUserDefaults 被缓存。
If you are just doing strings, you could use C arrays.
And if you occasionally need a true NSArray or NSDictionary from that:
A plist will involve a disk hit and xml parsing for each collection. As far as I know only NSUserDefaults are cached.