之前一片文章中我们介绍了OC中的两个关键字 @property 和 @synthesize 的使用的使用,今天我们来看一下OC中数组对象在是如何处理对象元素的引用计数问题的,同时介绍一下自动释放池的相关概念

 

一、数组对象是如何处理对象元素的引用计数问题

 1 //  
 2 //  main.m  
 3 //  26_NSArrayMemeryManager  
 4 //  
 5 //  Created by jiangwei on 14-10-12.  
 6 //  Copyright (c) 2014年 jiangwei. All rights reserved.  
 7 //  
 8   
 9 #import <Foundation/Foundation.h>  
10   
11 #import "Dog.h"  
12   
13 int main(int argc, const charchar * argv[]) {  
14       
15     Dog *dog1 = [[Dog alloc] init];  
16     Dog *dog2 = [[Dog alloc] init];  
17       
18     NSMutableArray *array = [[NSMutableArray alloc] init];  
19       
20     //数组会对每一个元素retain  
21     [array addObject:dog1]; //dog1计数=2  
22     [array addObject:dog2]; //dog2计数=2  
23       
24     [dog1 release];  
25     [dog2 release];  
26       
27     //当数组销毁的时候,会将所有的元素release  
28     [array release];//数组销毁  
29       
30     //当数组移除所有的元素的时候,会讲所有的元素release  
31     [array removeAllObjects];  
32       
33     return 0;  
34 }  

我们定义了Dog类,然后定义了NSMutableArray数组存放两个Dog对象,OC中在将对象放到数组中的时候,会自动调用retain方法,当数组对象本身被销毁的时候,会调用所有元素的release方法,当移除数组中所有的元素的时候,会调用元素的release方法 

二、自动释放池的概念

 1 //  
 2 //  main.m  
 3 //  27_AutoReleasePool  
 4 //  
 5 //  Created by jiangwei on 14-10-13.  
 6 //  Copyright (c) 2014年 jiangwei. All rights reserved.  
 7 //  
 8   
 9 #import <Foundation/Foundation.h>  
10   
11 #import "Dog.h"  
12   
13 int main(int argc, const charchar * argv[]) {  
14       
15     /* 
16     //创建一个自动释放池 
17     //有作用域的问题,在{}中定义的东西外部是不能访问的,这点和NSAutoreleasePool有区别的 
18     @autoreleasepool {//等价于[[NSAutoreleasePool alloc] init] 
19         
20         Dog *dog2 = [[Dog alloc] init]; 
21         [dog2 retain]; 
22          
23     }//等价于[pool release] 
24      
25     //创建一个自动释放池 
26     NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; 
27      
28     Dog *dog1 = [[Dog alloc] init];//计数:1 
29      
30     //将dog1对象加入到自动释放池中,却别于之前的release方法 
31     //加入到自动释放池中之后,不是代表我们不需要管理引用了,只是自动释放池自动会调用一次release 
32     //当自动释放池销毁的时候,释放池会对池中每一个对象调用一次release 
33     [dog1 autorelease]; 
34     NSLog(@"dog1计数:%ld",dog1.retainCount); 
35      
36     //销毁自动释放池 
37     //这时候会调用dog1的release方法,dog1对象就被销毁了 
38     [pool release]; 
39     */  
40       
41     //自动释放池的嵌套  
42     NSAutoreleasePool *pool1 = [[NSAutoreleasePool alloc] init];  
43       
44     //添加我们的代码  
45     //dog1放到了pool1中  
46     Dog *dog1 = [[Dog alloc] init];  
47     [dog1 autorelease];  
48       
49     //自动释放池的嵌套  
50     NSAutoreleasePool *pool2 = [[NSAutoreleasePool alloc] init];  
51       
52     //dog2放到了pool2中  
53     Dog *dog2 = [[Dog alloc] init];  
54     [dog2 autorelease];  
55       
56     //pool2销毁了  
57     [pool2 autorelease];  
58       
59     //pool1销毁了  
60     [pool1 release];  
61       
62       
63     //下面的代码就是有问题的  
64     //[person setDog:[[Dog alloc] init];  
65     //正确的写法  
66     //Dog *dogs = [[[Dog alloc] init] autorelease];  
67       
68       
69        
70     return 0;  
71 } 

我们在之前的文章中,定义一个对象的时候都会产生一个自动释放池,然后在释放池中编写我们的代码,自动释放池是系统提供的一种帮助我们去管理对象的引用计数问题。但是有时候代码必须在{...}中编写,这样的话就会产生作用域的问题,就是在{...}中定义的变量,在{...}外面不能使用。所以OC中就有了另外的一种方式:NSAutoreleasePool这个类。

这种自动释放池可以实现嵌套

1 NSAutoreleasePool *pool1 = [[NSAutoreleasePool alloc] init];
2 
3 //write code...
4 
5  
6 
7 //pool1销毁了
8 
9 [pool1 release];

上面的代码就相当于建立了一个自动释放池pool1,但是在这个中间的代码,如果要加入到这个池中,必须调用autorelease方法:

1 //dog1放到了pool1中  
2 Dog *dog1 = [[Dog alloc] init];  
3 [dog1 autorelease];  

而且,这样定义一个池子还可以嵌套使用,直接看上面的例子代码,这样这个自动释放池我们就可以控制了。比系统提供的自动释放池可操作的地方很多。

下面就直接对比一下:

1 NSAutoreleasePool *pool1 = [[NSAutoreleasePool alloc] init];
2 {
3         [pool1 release];//这行代码就相当于系统自动释放池的
4 }

这样就好理解了吧

 

总结

这一篇文章主要介绍了OC中数组对象操作元素对象的时候需要处理的引用问题,以及我们可以自定义一个自动释放池,这种方式比系统提供的自动释放池方便,可操作性强。

posted on 2015-01-03 14:35  I.L.L  阅读(384)  评论(0编辑  收藏  举报