此问题已在 iOS 5.1.1 中修复。对于那些使用 5.1 的用户,我已经实现了自己的内存看门狗,并发出了类似于发出真实内存警告时使用的通知。
我首先在UIApplication
. 这会发布一个通知,该通知会UIImage
侦听(或其后备缓存是什么)以卸载缓存的图像。
。H
@interface UIApplication (ForceLowMemory)
+ (void) forceUnload;
@end
.m
#import "UIApplication+ForceLowMemory.h"
@implementation UIApplication (ForceLowMemory)
+ (void)forceUnload {
[[NSNotificationCenter defaultCenter] postNotificationName:UIApplicationDidReceiveMemoryWarningNotification
object:[UIApplication sharedApplication]];
}
@end
接下来,我创建了一个内存管理器看门狗,如下所示:
。H
@interface ELMemoryManager : NSObject
- (void)startObserving;
- (void)stopObserving;
+ (ELMemoryManager*) sharedInstance;
@end
.m
#import "ELMemoryManager.h"
#import "UIApplication+ForceLowMemory.h"
#import <mach/mach.h>
@interface ELMemoryManager()
@property (nonatomic, retain) NSTimer *timer;
uint report_memory(void);
@end
#define MAX_MEM_SIZE 475000000
@implementation ELMemoryManager
@synthesize timer = timer_;
static ELMemoryManager* manager;
#pragma mark - Singleton
+ (void) initialize {
if (manager == nil) {
manager = [[ELMemoryManager alloc] init];
}
}
+ (ELMemoryManager*) sharedInstance {
return manager;
}
#pragma mark - Instance Methods
uint report_memory(void) {
struct task_basic_info info;
mach_msg_type_number_t size = sizeof(info);
kern_return_t kerr = task_info(mach_task_self(),
TASK_BASIC_INFO,
(task_info_t)&info,
&size);
if( kerr == KERN_SUCCESS ) {
return info.resident_size;
} else {
return 0;
}
}
- (void)startObserving {
if (!self.timer) {
NSTimer* timer = [NSTimer scheduledTimerWithTimeInterval:5.0f target:self selector:@selector(checkMemory:) userInfo:nil repeats:YES];
self.timer = timer;
}
[self.timer fire];
}
- (void)stopObserving {
[self.timer invalidate];
self.timer = nil;
}
- (void)checkMemory:(id)sender {
uint size = report_memory();
if (size > MAX_MEM_SIZE) {
NSLog(@"we've busted the upper limit!!!");
[UIApplication forceUnload];
}
}
#pragma mark - Memory Management
- (void)dealloc {
[self.timer invalidate];
[timer_ release];
[super dealloc];
}
@end