我正在构建一个具有多个不同部分的应用程序,所有部分都非常重要。它与我的客户的网站联系在一起,他们是一个“高设计”类型的服装。
应用程序的一部分是从相机或库上传的图像,以及显示缩略图网格的tableview。非常可靠,当我处理相机版本的UIImagePickerControl时,我会因为内存不足而受到打击。如果我在应用程序的那部分内部反弹了一段时间,我偶尔会在调试器中以“status:10(SIGBUS)”的形式不可重复地崩溃。
在内存不足警告时,应用程序该方面的根视图控制器进入我的数据管理单例,通过缓存数据阵列巡航,并杀死最大的部分,即与每个条目关联的图像。正是如此:
- (void)didReceiveMemoryWarning {
// Releases the view if it doesn't have a superview.
[super didReceiveMemoryWarning];
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Low Memory Warning"
message:@"Cleaning out events data"
delegate:nil
cancelButtonTitle:@"All right then."
otherButtonTitles:nil];
[alert show];
[alert release];
NSInteger spaceSaved;
DataManager *data = [DataManager sharedDataManager];
for (Event *event in data.eventList) {
spaceSaved += [(NSData *)UIImagePNGRepresentation(event.image) length];
event.image = nil;
spaceSaved -= [(NSData *)UIImagePNGRepresentation(event.image) length];
}
NSString *titleString = [NSString stringWithFormat:@"Saved %d on event images", spaceSaved];
for (WondrMark *mark in data.wondrMarks) {
spaceSaved += [(NSData *)UIImagePNGRepresentation(mark.image) length];
mark.image = nil;
spaceSaved -= [(NSData *)UIImagePNGRepresentation(mark.image) length];
}
NSString *messageString = [NSString stringWithFormat:@"And total %d on event and mark images", spaceSaved];
NSLog(@"%@ - %@", titleString, messageString);
// Relinquish ownership any cached data, images, etc that aren't in use.
}
正如你所看到的那样,我正在做一个(可怜的)尝试,以便将我正在释放的记忆空间留意。我知道它并没有告诉我UIImages本身的实际内存占用量,但它至少给了我一些数字,所以我可以看到有些东西正在发生。 (对不起,我也建立了这个NSLog消息的方式 - 我打算开另一个UIAlertView,但意识到记录它会更有用。)
非常可靠,在应用程序的图像部分中徘徊了一段时间之后,我将拉起相机界面并快速连续获得三次或四次低内存UIAlertView。这是我上次看到它时的NSLog输出:
2010-05-27 08:55:02.659 EverWondr[7974:207] Saved 109591 on event images - And total 1419756 on event and mark images
wait_fences: failed to receive reply: 10004003
2010-05-27 08:55:08.759 EverWondr[7974:207] Saved 4 on event images - And total 392695 on event and mark images
2010-05-27 08:55:14.865 EverWondr[7974:207] Saved 4 on event images - And total 873419 on event and mark images
2010-05-27 08:55:14.969 EverWondr[7974:207] Saved 4 on event images - And total 4 on event and mark images
2010-05-27 08:55:15.064 EverWondr[7974:207] Saved 4 on event images - And total 4 on event and mark images
然后很快我们得到了SIGBUS退出。这就是情况。现在我的具体问题:
我发现这种情况的时候是UIPickerView的相机光圈关闭的时候。我点击按钮拍照,它做“点击”动画,仪器显示我的内存占用量从大约10mb到大约25mb,并坐在那里直到图像被传送到我的UIViewController,其中使用率回落到10或11mb再次。如果我们在没有记忆警告的情况下通过它,我们就是金色的,但我们很可能不会。我能做些什么才能让它变得那么贵?
其次,我启用了NSZombies。我是否正确理解这实际上是在阻止内存被释放?我是否将我的应用程序置于不公平的测试环境中?
第三,有没有办法以编程方式获取内存使用情况?或者至少是UIImage对象的用法?我已经搜索过这些文档而且没有看到任何相关内容。
答案 0 :(得分:4)
这些功能可让您了解总内存使用量和总可用内存。我碰巧在我的应用程序中有一个1秒的计时器,它每秒记录一次和可用的内存空间(如果更改> 0.5mb),它可以帮助我看到更好的事情:
#import "mach/mach.h"
vm_size_t usedMemory(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);
return (kerr == KERN_SUCCESS) ? info.resident_size : 0; // size in bytes
}
natural_t freeMemory(void) {
mach_port_t host_port = mach_host_self();
mach_msg_type_number_t host_size = sizeof(vm_statistics_data_t) / sizeof(integer_t);
vm_size_t pagesize;
vm_statistics_data_t vm_stat;
host_page_size(host_port, &pagesize);
(void) host_statistics(host_port, HOST_VM_INFO, (host_info_t)&vm_stat, &host_size);
return vm_stat.free_count * pagesize;
}
EDIT1 - 函数class_getInstanceSize为您提供了对象实例的大小,但我从未尝试过它,它可能不会取消引用ivars并汇总它们的用法。但也许它可以帮助你。
EDIT2 此函数为您提供UIImage的大小:
size_t sizeofUIImage(UIImage* image) {
return CGImageGetBytesPerRow(image.CGImage) * CGImageGetHeight(image.CGImage);
}
EDIT4 以下是我的1秒计时器处理程序方法的一些代码,它有助于了解您的应用程序在出现内存问题之前的表现。当然,可用内存根据您无法控制的后台任务(Safari,Mail等)而有所不同:
void logMemUsage(void) {
// compute memory usage and log if different by >= 100k
static long prevMemUsage = 0;
long curMemUsage = usedMemory();
long memUsageDiff = curMemUsage - prevMemUsage;
if (memUsageDiff > 100000 || memUsageDiff < -100000) {
prevMemUsage = curMemUsage;
NSLog(@"Memory used %7.1f (%+5.0f), free %7.1f kb",
curMemUsage/1000.0f, memUsageDiff/1000.0f, freeMemory()/1000.0f);
}
}