应用程序因内存使用率非常低而崩溃 iphone/iPad

Posted

技术标签:

【中文标题】应用程序因内存使用率非常低而崩溃 iphone/iPad【英文标题】:App crashes with very low memory usage iphone/iPad 【发布时间】:2012-07-22 19:00:45 【问题描述】:

我已经阅读了很多关于内存不足警告崩溃的帖子,但是我无法解决我的应用程序崩溃的问题。仪器的分配显示 2-7MB 的实时字节。它永远不会超过 7 或 7.5MB,但应用程序仍然会崩溃。

我阅读了一些链接,这些链接告诉分配和活动监视器显示不同的内存使用值。如前所述,分配将显示最大 7-7.5MB,但活动监视器显示应用程序启动时大约 75MB 的使用量,当我使用该程序时,它开始增加和减少。它将增加到 110-120MB,然后减少到 75-80MB。

还有一些链接说要查看 VM Tracker 中的脏大小和驻留大小。当我签入 VM Tracker 时,Dirty 大小将从 30MB 开始,并随着我使用该应用程序而开始增加。它超过 400MB。我正在使用大约 150 张图像,其中大约 70-80 张是 1024x1024 尺寸的,大约 35 张是 110x110 尺寸的,其余的是 3000x4000 尺寸的图像。所有这些图像最初都是 png 格式,我已经以编程方式转换为 JPG+ALPHA 并作为资产添加到应用程序中。每当需要加载相应的图像时,我将 JPG+ALPHA 图像分成 16 个部分,最后将它们连接起来得到原始图像。我这样做是因为当我尝试加载分辨率为 3000x4000 的图像时,内存在分配中飙升至 40-45MB,所以使用了这种方法。此方法可确保内存永远不会超过 10MB。

所有这些记录和统计数据都是使用模拟器测量的。

应用程序永远不会在模拟器上崩溃,但它会在真实设备上崩溃。我正在使用 iPad2 进行测试。

请帮我解决这个问题。过去 2 天我被困住了,看到应用程序崩溃完全沮丧。

【问题讨论】:

搜索heapshots,这是分配工具的一个功能。您可以跟踪在特定时间间隔内分配和解除分配的内存。另外,仅供参考,一些图像处理方法使用缓存,例如imageNamed。你也可以试试NSAutoreleasePool,因为内存中同时有很多图片。 崩溃日志说什么...? 感谢@Templar 的回复。我在任何地方都使用过 NSAutoreleasePool 并且正在使用 initWithContentsOfTheFile 来加载图像的内容。将尝试使用 heapshots 并在此处发布结果。 如果由于内存不足警告而崩溃,那么您肯定不会在 viewDidUnload 中设置 nil 某些对象 @AnkitSrivastava 崩溃日志显示“被抛弃”。正如我在一些帖子中所读到的,抛弃意味着由于内存不足警告而崩溃。我说的对吗? 【参考方案1】:

这段代码正确吗?

    UIImageView* framebadgeOrAccessoryImage = [[UIImageView alloc]initWithFrame:sizeOfFrameOrAccessoriesView];
    [framebadgeOrAccessoryImage setCenter:imageArea.center];
    [framebadgeOrAccessoryImage setContentMode:UIViewContentModeScaleAspectFit];
    [framebadgeOrAccessoryImage setImage:badgeOrAccessoryImage];
    [framebadgeOrAccessoryImage setTag:iObjectTag];
    [framebadgeOrAccessoryImage setObservationInfo:@"BadgeAccessories"];
    [framebadgeOrAccessoryImage setExclusiveTouch:YES];

    iObjectTag++;

    [framebadgeOrAccessoryImage setMultipleTouchEnabled:YES];
    [framebadgeOrAccessoryImage setBackgroundColor:[UIColor clearColor]];
    [framebadgeOrAccessoryImage setUserInteractionEnabled:YES];

    [imageArea addSubview:framebadgeOrAccessoryImage];

selectedItem = framebadgeOrAccessoryImage;

    [framebadgeOrAccessoryImage release];

我使用我设置的标签在其他方法中使用“framebadgeOrAccessoryImage”。我是否必须像我在代码的最后一行中所做的那样释放“framebadgeOrAccessoryImage”,还是在释放后将其分配给 nil?

“framebadgeOrAccessoryImage”在这里使用名称“selectedItem”。

- (void)panRecognized:(UIPanGestureRecognizer *)gestureRecognizer
   
    if(selectedItem.image && [gestureRecognizer isEnabled])
    
        UIImageView *piece = selectedItem;

        if ((([gestureRecognizer state] == UIGestureRecognizerStateBegan || [gestureRecognizer state] == UIGestureRecognizerStateChanged)) && [((NSString*) [piece observationInfo]) isEqualToString:@"BadgeAccessories"])
        
            CGPoint translation = [gestureRecognizer translationInView:[piece superview]];
            [piece setCenter:CGPointMake([piece center].x + translation.x, [piece center].y + translation.y)];
            [gestureRecognizer setTranslation:CGPointZero inView:[piece superview]];

        

        if ([gestureRecognizer state] == UIGestureRecognizerStateEnded ||[gestureRecognizer state] == UIGestureRecognizerStateCancelled || [gestureRecognizer state] == UIGestureRecognizerStateFailed)
           
            if(CGRectContainsPoint([[self view]viewWithTag:RECYCLEBIN_TAG].frame, [gestureRecognizer locationInView:imageArea]))
            
                NSAutoreleasePool* pool = [[NSAutoreleasePool alloc]init];
                [objectsAdded removeObjectForKey:[NSString stringWithFormat:@"%d",selectedItem.tag]];
                [pool release];
                [UIView beginAnimations:NULL context:nil];
                [UIView setAnimationBeginsFromCurrentState:YES];
                [UIView setAnimationDuration:0.4];
                [UIView setAnimationDidStopSelector:@selector(propDeleted:finished:context:)];
                [UIView setAnimationDelegate:self];

                [selectedItem setFrame:CGRectMake(selectedItem.frame.origin.x, selectedItem.frame.origin.y, 5, 5)];
                selectedItem.center = [[[self view]viewWithTag:RECYCLEBIN_TAG]center];
                [UIView commitAnimations];
            
            else
            
                [self applyEffectOnTouch:0];
            
        
    

【讨论】:

请显示使用framebadgeOrAccessoryImage的其他代码。这听起来很可能是问题所在。但是,请不要把你的代码放在这里。这个区域是为了回答。使用问题下方的 Edit 链接,并将代码放入您的问题中。谢谢。【参考方案2】:

您尝试加载的图像非常大。也许您应该考虑使用 CATiledLayer 来显示图像。你可以找到苹果类定义here。

还要考虑使图像更易于渲染与减少图片的内存使用之间的区别。如果您将图像分割成更小的部分,您将减少单独的绘制负载,但如果将这些图像中的每一个都加载到内存中,您仍然会遇到内存问题。

平铺层显示非常大的图像,同时通过尝试仅加载可见平铺来降低内存使用量。

此外,您的模拟器没有实际设备的内存限制。您应该在实际设备上执行所有压力测试。

编辑:您还应该避免使用 UIImage imageNamed,因为它会缓存图像并且会使您的内存问题更加严重。请改用 imageWithContentsOfFile。

【讨论】:

谢谢。我正在使用“imageWithContentsOfFile”方法。由于我的包中有 JPG+ALPHA 分隔的图像,因此我需要将这些图像转换为 png 文件,然后再将其显示在屏幕上。我不能使用 CATiledLayer,因为我必须事先将 JPG+ALPHA 转换为 png。正如我在帖子前面所说的,Allocations 记录的内存最大为 7-7.5MB,但在 VM Tracker 中,Dirty 大小达到了大约 400MB。如何减小 Dirty 大小或如何声明这部分内存?

以上是关于应用程序因内存使用率非常低而崩溃 iphone/iPad的主要内容,如果未能解决你的问题,请参考以下文章

UIWebView 应用程序因内存压力而崩溃

xcode 使用 iOS 10 设备构建项目,但启动时崩溃:来自调试器的消息:因内存问题而终止

将更改的图像保存到相机胶卷时因内存问题而终止

iOS:浏览器因内存不足而崩溃

当图像保存在核心数据的集合视图中时,应用程序因内存错误而崩溃

部署“react-admin”应用程序时,Heroku 服务器因“JavaScript 堆内存不足”而崩溃