现在的位置: 首页 > 综合 > 正文

属性与内存管理二

2018年01月23日 ⁄ 综合 ⁄ 共 3189字 ⁄ 字号 评论关闭
  1. <span style="font-size:24px;">四,关于语义特性copy和与alloc对应的dealloc以及初始化操作和便利构造器的补充  
  2.   
  3. 1, 语义特性copy  
  4.   
  5. 如果想对一个对象进行copy操作,对象的类必须服从一个NSCopying协议,并且实现协议中的方法copyWithZone:,方法为(仍以Person类为例):  
  6.   
  7. -(id)copyWithZone:(NSZone*)zone  
  8.   
  9. {  
  10.   
  11.     NSString*newSex = [[NSStringallocWithZone:zone]init];  
  12.   
  13.     newSex.sex = self.sex;  
  14.   
  15.     returnnewSex;  
  16.   
  17. }  
  18.   
  19. 其中copyWithZone: 是协议NSCopying制定的方法,  
  20.   
  21. 2, dealloc  
  22.   
  23. 对于dealloc方法,由于系统不知道我们在开发程序时会对那些对象的语义特性声明为retain或者copy,所以需要我们重写dealloc方法,即如下:  
  24.   
  25. -(void)dealloc  
  26.   
  27. {  
  28.   
  29.  [_namerelease];  
  30.   
  31.  [_sexrelease];  
  32.   
  33.  NSLog(@"Person空间回收了");  
  34.   
  35.  [superdealloc];  
  36.   
  37. }  
  38.   
  39. (1), [_namerelease]和[_sexrelease]操作目的:当调用dealloc方法时,该对象的空间将要被系统回收,在空间回收之前,将保有的其他对象()的所有权给释放掉,当该类对象的引用计数为0时,会自动调用该类的dealloc方法  
  40.   
  41. (2), [superdealloc]该操作即必须通过super调用父类的方法实现,才能将空间回收,  
  42.   
  43. 3, 初始化操作  
  44.   
  45. -(id)initWithName:(NSString*)name sex :( NSString *)sex  
  46.   
  47. {  
  48.   
  49.     self =[superinit];  
  50.   
  51.     if (self) {  
  52.   
  53.         self.name = name;  
  54.   
  55.         self.sex = sex;  
  56.   
  57.     }  
  58.   
  59.     returnself;  
  60.   
  61. }  
  62.   
  63. (1),使用self.name = name赋值方法,self.name时调用了setter方法,内部对name进行了retain操作,即_name也保留了name的使用权,如果使用_name = name即直接赋值方法,则就表示把属性的语义特性设为asgin,这时如果name的空间已经被回收了,直接赋值就会出现野指针问题  
  64.   
  65. 使用self.sex = sex同理;  
  66.   
  67. (4),便利构造器  
  68.   
  69. +(id)teacherWithName:(NSString*)name sex :( NSString *)sex  
  70.   
  71. {  
  72.   
  73.   Person*person = [[Person alloc] initWithName:namesex:sex];  
  74.   
  75.     return [Personautorelease];  
  76.   
  77. }  
  78.   
  79. 我们在使用便利构造器时不需要再对其进行release操作,因为内部已经做了autorelease操作,如果在进行release操作会造成过度释放,以后我们再写便利构造器就要这样写.  
  80.   
  81. 五,collection(集合) 的内存管理  
  82.   
  83. 当把一个对象放入集合(数组,字典,集合)中时,会将对象的引用计数 + 1,因为内部做了retain操作  
  84.   
  85. 例如: Person *per1 = [[Personalloc] initWithName:@"Frank"sex:@"boy"];  
  86.   
  87.         Person *per2= [[Personalloc] initWithName:@"Duke"sex:@"boy"];  
  88.   
  89. 此时per1和per2所指向的空间的引用计数都为1,  
  90.   
  91. NSMutableArray *array =[[NSMutableArray alloc ]initWithObjects:per1,per2, nil nil];  
  92.   
  93.  这里使用便利构造器,其内部给添加到数组中的元素进行了autorelease操作,这时per1和per2所指向的空间的引用计数都为2,  
  94.   
  95. 当集合(数组,字典,集合)空间被回收时,他们会向容器中的每个元素发送一个release消息(对应添加元素时的retain操作),当从集合(数组,字典,集合)中移除一个元素时,会release该对象,引用计数 - 1;  
  96.   
  97. 下面把对该数组对象以及存储的对象的进行release操作  
  98.   
  99. (1),[per1release];  
  100.   
  101.         [per2release];  
  102.   
  103.         NSLog(@"%lu",[ per1retainCount]);  
  104.   
  105.         NSLog(@"%lu",[ per2retainCount]);  
  106.   
  107.         此时 per1和per2所指向的空间的引用计数都为1, array所指向的空间的引用计数为1,  
  108.   
  109. NSLog(@"%@",array);  此时会输出数组中的内容  
  110.   
  111.         [per1release];  
  112.   
  113.         [per2release];  
  114.   
  115. 此时per1和per2的空间都被回收,因为系统识别到他们的引用计数都为0  
  116.   
  117.         NSLog(@"%@",array);此时若再执行该操作系统会crash,因为数组中存储的对象已经被系统回收了,如果输出相当于又对数组中被回收的空间进行操作,是野指针问题  
  118.   
  119. NSLog(@"arrayCount= %lu",[array retainCount]);  
  120.   
  121. 此时array所指向的空间的引用计数为1,因为array的空间没有被回收,但不可以输出数组  
  122.   
  123. (2),[array release];  
  124.   
  125. 此时array所指向的空间被系统回收  
  126.   
  127.         NSLog(@"%lu",[tea1retainCount]);  
  128.   
  129.         NSLog(@"%lu",[tea2retainCount]);  
  130.   
  131. 此时per1和per2所指向的空间的引用计数都为1,  
  132.   
  133.         NSLog(@"%@",array);此时若再执行该操作系统会crash, 因为数组已经被回收, 如果输出相当于对被回收的数组进行操作,是野指针问题  
  134.   
  135.  [per1release];  
  136.   
  137. [per2release];  
  138.   
  139. 此时per1和per2的空间都被回收,因为系统识别到他们的引用计数都为0  
  140.   
  141. NSLog(@"arrayCount= %lu",[array retainCount]);  
  142.   
  143. 若进行此操作,会crash, 因为array的空间已经被回收  
  144.   
  145.   
  146. (3),  [per1release];  
  147.   
  148.         [per2release];  
  149.   
  150. 此时per1和per2所指向的空间的引用计数都为1, array所指向的空间的引用计数为1,  
  151.   
  152.         [arrayrelease];  
  153.   
  154. 此时array所指向的空间被系统回收,per1和per2的空间也都被回收,当集合(数组,字典,集合)空间被回收时,他们会向容器中的每个元素发送一个release消息(对应添加元素时的retain操作),即此时per1和per2的空间都被回收,因为他们收到</span>
     
【上篇】
【下篇】

抱歉!评论已关闭.