IOS 記憶體警告 Memory warning level

來源:互聯網
上載者:User

記憶體警告

  我們都知道在行動裝置上很多資源都是比較緊缺的,尤其時記憶體,通常都比較小,iPhone4也才只有512MB。而且IOS4.0以後還支援了多任務,這個問題就更加突出了。因此我們在平時設計程式的時候要注意管理好記憶體,減少不必要的開銷,謹防泄露。

  由於寫的一個小項目存在嚴重的記憶體流失,程式經常已耗用時間不長就退出了,調試時候發現運行過程中接受到系統的Memry warning level 1幾次以後,緊接著收到一個Memory warning level 2,然後程式退出。通常使用xcode4內建的工具,跟蹤發現由於一個映像資源忘記release導致。問題解決了,但我沒有打算就此帶過。接著上網尋找了有關Memory warning Level的資料,後來在stackoverflow上面找到一些有用的資料,這是KennyTM寫的,跟大家分享一下:

    系統有四種記憶體警告,定義如下:

    typedef enum {

        OSMemoryNotificationLevelAny      = -1,

        OSMemoryNotificationLevelNormal   =  0,

        OSMemoryNotificationLevelWarning  =  1,

        OSMemoryNotificationLevelUrgent   =  2,

        OSMemoryNotificationLevelCritical =  3

    } OSMemoryNotificationLevel;

  但是這幾種警告之間是怎麼變化的,到達什麼閾值時會從一個level跳到另外一個level,文章中沒有提及。

  通常我們在程式中接收到最多的就是Memory warning level 1,這個時候就證明系統記憶體緊張了,我們的程式必須做出相應,釋放不必要的記憶體。通常如果我們處理得當的話,記憶體警告就會到此停止,恢複正常狀態。如果我們在接收到memory warning level 1以後坐視不理的話,系統可能還會再嘗試通知幾次level 1,如果還是不去處理的話,系統將會發出更高一級的記憶體警告 level 2,通常的結果就是我們的App被強制退出,系統收回記憶體。當然系統在發出level 2的警告時,也會取嘗試做一些清理記憶體的事,例如關閉不必要的背景程式等。很顯然我們不該寄希望於系統自己清理,這就好比你的胳膊被劃破了,身體肯定會有自修複功能,但是如果傷口比較大的話,肯定還是需要人工處理一下的。

  到目前位置我還沒有見過level 3的警告,根據stack over flow上面講的“當發生level 3警告時,系統核心將會接管,很有可能關掉IOS的主介面進程(SpringBorad),甚至會重啟”,照這個意思來說我們程式裡面接收不到,也實屬正常,系統自己的東西都被幹掉了,我們肯定早被kill了。

  KennyTM寫的原文地址: http://stackoverflow.com/questions/2915247/iphone-os-memory-warnings-what-do-the-different-levels-mean

  如果開啟上面的串連,可以看到定義OSMemoryNotificationLevel的源檔案,你可能會注意到裡面有一個函數OSMemoryNotificationCurrentLevel()可以用來擷取當前記憶體警示level,不過需要加標頭檔#import <libkern/OSMemoryNotification.h>,網上有個查看當前記憶體資料的開原始碼MemWatcher,大家可以看看,說實話我沒有看懂。

  說了這麼多,希望能幫大家弄清楚記憶體警告是怎麼回事兒,通常我們程式是不會碰到記憶體警告,平時寫代碼注意在所有alloc,retain,copy的地方,對應的寫上release,或者直接建立autorelease對象(個人不推薦這麼做),發布前養成檢查記憶體泄露的好習慣。

  順便提一下如果運行過程中遇到記憶體警告的話,程式通常情況下都先調用AppDelegate中的applicationDidReceiveMemoryWarning, 然後程式會通知各ViewController,調用其didRecieveMemoryWarning方法,這個時候我們一定要種,釋放不必要的資源。

  ~~~~~~~~~~~~~~~~~~~~~~3月9號更新~~~~~~~~~~~~~~~~~~~~~~

  今天回家寫了個小例子測試記憶體流失,思路如下:在UIViewController的viewDidload中,向self.view添加一個自訂的專門泄漏的UIView(在初始化函數中開啟一個線程不停的家在圖片)。在我的iPhone4下運行程式後大概不到一分鐘以後出現level 1 警告,然後過10秒左右報出level 2警告,再過5秒左右程式被退出。如下:

  這也證明前面說過的level 3的警告通常我們是接收不到的這個推斷。

 

SvMemoryWarningViewController.m

//
// SvMemoryWarningViewController.m
// SvMemoryWarning
//
// Created by maple on 3/9/12.
// Copyright (c) 2012 SmileEvday. All rights reserved.
//

#import "SvMemoryWarningViewController.h"
#import <libkern/OSMemoryNotification.h>
#import "SvLeakMemoryView.h"

@interface SvMemoryWarningViewController ()

@end

@implementation SvMemoryWarningViewController

- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.

SvLeakMemoryView *view = [[SvLeakMemoryView alloc] initWithFrame:CGRectMake(0, 0, 320, 480)];
[self.view addSubview:view];
[view release];
}

- (void)viewDidUnload
{
[super viewDidUnload];
// Release any retained subviews of the main view.
}

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return interfaceOrientation == UIInterfaceOrientationPortrait;
}

- (void)didReceiveMemoryWarning
{

NSLog(@"Recieve memory warning");
NSLog(@"~~~~~~~~~~~~~~level~~~~~~~~~~~~~~~ %d", (int)OSMemoryNotificationCurrentLevel());
}

@end

 

SvLeakMemoryView.m

#import "SvLeakMemoryView.h"
#import <QuartzCore/QuartzCore.h>

@implementation SvLeakMemoryView

- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// Initialization code

UIImageView *imageView = [[UIImageView alloc] initWithFrame:frame];

NSString *filePath = [[NSBundle mainBundle] pathForResource:@"Car" ofType:@"jpg"];
imageView.image = [[UIImage alloc] initWithContentsOfFile:filePath];

imageView.layer.contentsGravity = kCAGravityResizeAspect;
[self addSubview:imageView];

NSString *filePath2 = [[NSBundle mainBundle] pathForResource:@"treeHighResolution" ofType:@"jpg"];
dispatch_queue_t loadImageQueue = dispatch_queue_create("load image", NULL);

__block UIImageView *testIV = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 320, 480)];
dispatch_async(loadImageQueue, ^{
while (TRUE) {
UIImage *image = [[UIImage alloc] initWithContentsOfFile:filePath2];
testIV.image = image;
}
});
}
return self;
}

/*
// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect
{
// Drawing code
}
*/

@end




  

 

  

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.