UIImagePicker的内存故障 [英] Memory Troubles with UIImagePicker

查看:108
本文介绍了UIImagePicker的内存故障的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在建立一个应用程式,它有几个不同的部分,它都是很漂亮的图像重。

I'm building an app that has several different sections to it, all of which are pretty image-heavy. It ties in with my client's website and they're a "high-design" type outfit.

该应用程序的一部分是从相机或图书馆上传的图片,和一个显示缩略图网格的tableview。相当可靠,当我处理的相机版本的UIImagePickerControl,我被打中低内存。如果我在应用程序的这一部分弹跳了一段时间,我偶尔和不可重复崩溃与调试程序中的状态:10(SIGBUS)。

One piece of the app is images uploaded from the camera or the library, and a tableview that shows a grid of thumbnails. Pretty reliably, when I'm dealing with the camera version of UIImagePickerControl, I get hit for low memory. If I bounce around that part of the app for a while, I occasionally and non-repeatably crash with "status:10 (SIGBUS)" in the debugger.

低内存警告,我的应用程序的方面的我的根视图控制器转到我的数据管理单例,巡航通过缓存数据的数组,并杀死最大的一块,与每个条目相关联的图像。因此:

On low memory warning, my root view controller for that aspect of the app goes to my data management singleton, cruises through the arrays of cached data, and kills the biggest piece, the image associated with each entry. Thusly:

- (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自己的实际内存足迹,但它给我至少一些数字,所以我可以看到SOMETHING的发生。 (对不起,我建立的NSLog消息太 - 我要发射另一个UIAlertView,但意识到它会更有用的日志。)

As you can see, I'm making a (poor) attempt to eyeball the memory space I'm freeing up. I know it's not telling me about the actual memory footprint of the UIImages themselves, but it gives me SOME numbers at least, so I can see that SOMETHING'S happening. (Sorry for the hamfisted way I build that NSLog message too--I was going to fire another UIAlertView, but realized it'd be more useful to log it.)

相当可靠,在app的图像部分滚动了一段时间后,我会拉起相机界面,并获得低内存UIAlertView快速连续三或四次。这是我上次看到它的NSLog输出:

Pretty reliably, after toodling around in the image portion of the app for a while, I'll pull up the camera interface and get the low memory UIAlertView like three or four times in quick succession. Here's the NSLog output from the last time I saw it:

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退出。这就是情况。现在我的具体问题:

And then pretty soon after that we get our SIGBUS exit. So that's the situation. Now my specific questions:

我看到这种情况发生的时候是当UIPickerView的相机虹膜关闭。我点击按钮拍摄图片,它做了点击动画,仪器显示我的内存占用从大约10mb到大约25mb,并坐在那里,直到图像传送到我的UIViewController,其中使用率回到10或11mb。如果我们通过没有内存警告,我们是金色的,但很可能我们没有。我可以做什么,使它不那么昂贵?

THE time I see this happening is when the UIPickerView's camera iris shuts. I click the button to take the picture, it does the "click" animation, and Instruments shows my memory footprint going from about 10mb to about 25mb, and sitting there until the image is delivered to my UIViewController, where usage drops back to 10 or 11mb again. If we make it through that without a memory warning, we're golden, but most likely we don't. Anything I can do to make that not be so expensive?

其次,我有NSZombies启用。我正确地理解,这实际上是防止内存释放?我会让我的应用程序受到不公平的测试环境吗?

Second, I have NSZombies enabled. Am I understanding correctly that that's actually preventing memory from being freed? Am I subjecting my app to an unfair test environment?

第三,有没有办法以编程方式获取我的内存使用?或者至少是UIImage对象的用法?

Third, is there some way to programmatically get my memory usage? Or at least the usage for a UIImage object? I've scoured the docs and don't see anything about that.

推荐答案

这些函数让你知道你的总内存使用和总可用内存。我碰巧在我的应用程序中有一个1秒的定时器,每秒钟它使用的日志和可用的内存空间(如果更改> 0.5mb),它有助于我看到更好的情况:

These functions give you an idea of your total memory usage and total free memory. I happen to have a 1 sec timer in my app, every second it logs used and free memory space (if either changed > 0.5mb), it helps me see better whats going on:

#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和汇总它们的用法。

EDIT1 - function class_getInstanceSize gives you the size of an object instance, but I've never tried it and it probably doesn't dereference the ivars and rollup their usage. But maybe it can help you.

EDIT2 此函数提供UIImage的大小:

EDIT2 This function gives you the size of a UIImage:

size_t sizeofUIImage(UIImage* image) {
    return CGImageGetBytesPerRow(image.CGImage) * CGImageGetHeight(image.CGImage);
}

EDIT4 1秒定时器处理程序方法,它有助于了解您的应用程序在您遇到内存问题之前如何做。当然,可用内存取决于你不能控制的后台任务运行(Safari,Mail等):

EDIT4 Here is a bit of code from my 1 sec timer handler method, it helps see how your app is doing before you have memory problems. Of course, free memory varies depending on what background tasks are running (Safari, Mail, etc) which you don't have much control over:

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);
    }
}


/ used从此处在这里

这篇关于UIImagePicker的内存故障的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆