我们在我们的应用程序中使用NSCache进行UIImages。这适用于小于7的iOS版本。当发生内存警告时,NSCache会按预期释放对象。 但是,在iOS 7上,我们的应用程序在第一次内存警告后不久崩溃。因此,似乎从未发布与NSCache一起存储的对象,但缓存正在增长,直到应用程序崩溃。用仪器进行分析证实了这种怀疑。
其他人是否遇到此问题,您是否找到了解决方法或已经跟踪过错误?
看起来这些人有同样的问题:http://www.photosmithapp.com/index.php/2013/10/photosmith-3-0-2-photo-caching-and-ios-7/
我创建了一个小样本应用来说明问题。按下按钮时,将调用方法-(IBAction)fillCache:(id)sender
。从那时起,计时器每100毫秒调用-(void)addImageToCache:(id)sender
。在此方法中,生成UIImage并将其写入缓存。
在带有iOS 7.0.3及其512 MB内存的iPad Mini上,它在大约350次迭代后崩溃。
在具有iOS 5和512 MB内存的iPad 2上,它也会在某些时候崩溃,但仅在至少3000次迭代后崩溃。仪器显示每次发生内存警告时,UIImage实例的数量会减少。在iOS 7上情况并非如此。
- (IBAction)fillCache:(id)sender
{
[NSTimer scheduledTimerWithTimeInterval:0.1 target:self selector:@selector(addImageToCache:) userInfo:nil repeats:YES];
}
- (void)addImageToCache:(id)sender
{
@autoreleasepool {
CGRect rect = CGRectMake(0, 0, 500, 500);
UIGraphicsBeginImageContextWithOptions(rect.size, NO, 0);
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
NSString *poolKey = [NSString stringWithFormat:@"junk_%d", count++];
[self.cache setObject:image forKey:poolKey];
}
}
答案 0 :(得分:16)
虽然NSCache
从未对内存警告做出响应,但我发现它通常会对真正的内存压力做出反应。无法响应内存警告一直是一种烦恼(例如,你不能只使用“模拟内存警告”来测试应用程序在内存压力下的行为)。
话虽如此,我看到你描述的行为相同。 iOS 7似乎改变了NSCache
行为。
就个人而言,我只有简单的NSCache
子类,只是在收到UIApplicationDidReceiveMemoryWarningNotification
通知后删除所有对象:
@implementation AutoPurgeCache
- (id)init
{
self = [super init];
if (self) {
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(removeAllObjects) name:UIApplicationDidReceiveMemoryWarningNotification object:nil];
}
return self;
}
- (void)dealloc
{
[[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationDidReceiveMemoryWarningNotification object:nil];
}
@end
答案 1 :(得分:3)
NSCache对象根据自己的规则删除其数据。这并不意味着它会在记忆警告期间释放内容 这里的文件说明了:
NSCache类包含各种自动驱逐策略 确保缓存不会占用太多的系统内存。如果 其他应用程序需要内存,这些策略会删除一些内存 来自缓存的项目,最小化其内存占用。
最有可能改变了iOS7中的一些策略。您可以通过收听内存警告通知来删除所有内容。为了完整起见,我将此answer链接起来。