在关闭ARC情况下对NSMutableArray存储内存分析。
一:测试环境构建
1:创建一个简单视窗工程 在AppDelegate.m
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window=[[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];//Override point for customization after application launch.
ViewController *viewCtrl =[[[ViewController alloc] initWithNibName:@"ViewController"bundle:nil] autorelease];
UINavigationController*navigationCtrl = [[UINavigationController alloc] initWithRootViewController:(UIViewController*) viewCtrl];
self.viewController= (ViewController*)navigationCtrl;
self.window.rootViewController=self.viewController;
[navigationCtrl release];
[self.window makeKeyAndVisible];returnYES;
}
2 在ViewController.m中
- (void)viewDidLoad
{
[super viewDidLoad];//Do any additional setup after loading the view, typically from a nib.
UIBarButtonItem *rightItm =[[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAction target:self action:@selector(rightTarget:)];
self.navigationItem.rightBarButtonItem=rightItm;
UIBarButtonItem*backButton = [[UIBarButtonItem alloc] initWithTitle:@"根视图"style:UIBarButtonItemStyleDone target:nil action:nil];
self.navigationItem.backBarButtonItem=backButton;
[backButton release];
[rightItm release];
}-(void)rightTarget:(id)sender
{
SecondViewController*secondViewCtrl =[[SecondViewController alloc] init];
[self.navigationController pushViewController:secondViewCtrl animated:YES];
[secondViewCtrl release];
}
3在 SecondViewController.h中申明如下:
NSMutableArray *arrayObj;
SecondViewController.m中实现
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self=[super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];if(self)
{//Custom initialization
[self.view setBackgroundColor: [UIColor grayColor] ];
[self initArrayData];
}returnself;
}-(void)initArrayData
{
arrayObj= [[NSMutableArray alloc] initWithCapacity:0];
DataSorceViewController*dataViewCtrl =nil;for (int i = 0 ; i < 1024; i++)
{
dataViewCtrl=[[DataSorceViewController alloc] init];
[arrayObj addObject: dataViewCtrl];
}
}-(void)viewWillDisappear:(BOOL)animated
{
for ( DataSorceViewController *data in arrayObj)
{
[data release];
data = nil;
}[arrayObj removeAllObjects];
[arrayObj release];
arrayObj=nil;
}
4 引入测试用的数据对象 DataSorceViewController,这里用的UIViewController子类,可以用任何类型的数据做为测试
二 :测试操作
1,SecondViewController.m 的 -(void)viewWillDisappear:(BOOL)animated 中不做任何操作。用profile memeory leak测试,当页面切换操作后发现,有红色标注,表示有内存泄漏。
2. -(void)viewWillDisappear:(BOOL)animated函数中加入
[arrayObj release];
arrayObj= nil;
切换页面,profile memeory leak中没有发现有红色标注,表示没有内存泄漏吗?其实不然,在Statistics的数据对象列表中,DataSorceViewController 对象始终存在,而且在多次切换操作中DataSorceViewController对象所占的内存每切换一次就会增长一次。多次切换后内存DataSorceViewController对象占用内存居高不下。
3:-(void)viewWillDisappear:(BOOL)animated函数中加入
[arrayObj removeAllObjects];
[arrayObj release];
arrayObj= nil;
效果同第二步。
4:增加对数组对象释放操作
for ( DataSorceViewController *data inarrayObj)
{
[data release];
data=nil;
}
[arrayObj removeAllObjects];
[arrayObj release];
arrayObj= nil;
在页面每次切换以后,DataSorceViewController 对象被释放。
结论:
一:profile memeory leak 检测,那个红色的标示并不是可靠的,即使有内存泄漏,leaks红色标示也可能没有出现
二:NSArray(NSMutableArray)数组,在 addObject 操作是会对对象做retain操作,同时 removeobject 操作会对对象做release操作,但数组中保存的对象所占的内存并没有释放,因为alloc操作时候retaincount 为1,一次addObject操作,retaincount 2,rimoveObject操作,retaincont为1,实际内存并没有得到释放。要真正释放内存,要遍历数组,对数组中保持的每个对象做release操作。 最后清除数组所有对象以及其本身。同理可得其它容器也是相同性质,比如NSDictionary等
三:以上为个人试验结论,如有不正确地方,欢迎指正!