四,关于语义特性copy和与alloc对应的dealloc以及初始化操作和便利构造器的补充
1, 语义特性copy
如果想对一个对象进行copy操作,对象的类必须服从一个NSCopying协议,并且实现协议中的方法copyWithZone:,方法为(仍以Person类为例):
-(id)copyWithZone:(NSZone*)zone
{
NSString*newSex = [[NSStringallocWithZone:zone]init];
newSex.sex = self.sex;
returnnewSex;
}
其中copyWithZone: 是协议NSCopying制定的方法,
2, dealloc
对于dealloc方法,由于系统不知道我们在开发程序时会对那些对象的语义特性声明为retain或者copy,所以需要我们重写dealloc方法,即如下:
-(void)dealloc
{
[_namerelease];
[_sexrelease];
NSLog(@"Person空间回收了");
[superdealloc];
}
(1), [_namerelease]和[_sexrelease]操作目的:当调用dealloc方法时,该对象的空间将要被系统回收,在空间回收之前,将保有的其他对象()的所有权给释放掉,当该类对象的引用计数为0时,会自动调用该类的dealloc方法
(2), [superdealloc]该操作即必须通过super调用父类的方法实现,才能将空间回收,
3, 初始化操作
-(id)initWithName:(NSString*)name sex:(NSString *)sex
{
self =[superinit];
if (self) {
self.name = name;
self.sex = sex;
}
returnself;
}
(1),使用self.name = name赋值方法,self.name时调用了setter方法,内部对name进行了retain操作,即_name也保留了name的使用权,如果使用_name = name即直接赋值方法,则就表示把属性的语义特性设为asgin,这时如果name的空间已经被回收了,直接赋值就会出现野指针问题
使用self.sex = sex同理;
(4),便利构造器
+(id)teacherWithName:(NSString*)name sex:(NSString *)sex
{
Person*person = [[Person alloc] initWithName:namesex:sex];
return [Personautorelease];
}
我们在使用便利构造器时不需要再对其进行release操作,因为内部已经做了autorelease操作,如果在进行release操作会造成过度释放,以后我们再写便利构造器就要这样写.
五,collection(集合) 的内存管理
当把一个对象放入集合(数组,字典,集合)中时,会将对象的引用计数 + 1,因为内部做了retain操作
例如: Person *per1 = [[Personalloc] initWithName:@"Frank"sex:@"boy"];
Person *per2= [[Personalloc] initWithName:@"Duke"sex:@"boy"];
此时per1和per2所指向的空间的引用计数都为1,
NSMutableArray *array =[[NSMutableArray alloc ]initWithObjects:per1,per2, nil];
这里使用便利构造器,其内部给添加到数组中的元素进行了autorelease操作,这时per1和per2所指向的空间的引用计数都为2,
当集合(数组,字典,集合)空间被回收时,他们会向容器中的每个元素发送一个release消息(对应添加元素时的retain操作),当从集合(数组,字典,集合)中移除一个元素时,会release该对象,引用计数 - 1;
下面把对该数组对象以及存储的对象的进行release操作
(1),[per1release];
[per2release];
NSLog(@"%lu",[ per1retainCount]);
NSLog(@"%lu",[ per2retainCount]);
此时 per1和per2所指向的空间的引用计数都为1, array所指向的空间的引用计数为1,
NSLog(@"%@",array); 此时会输出数组中的内容
[per1release];
[per2release];
此时per1和per2的空间都被回收,因为系统识别到他们的引用计数都为0
NSLog(@"%@",array);此时若再执行该操作系统会crash,因为数组中存储的对象已经被系统回收了,如果输出相当于又对数组中被回收的空间进行操作,是野指针问题
NSLog(@"arrayCount= %lu",[array retainCount]);
此时array所指向的空间的引用计数为1,因为array的空间没有被回收,但不可以输出数组
(2),[array release];
此时array所指向的空间被系统回收
NSLog(@"%lu",[tea1retainCount]);
NSLog(@"%lu",[tea2retainCount]);
此时per1和per2所指向的空间的引用计数都为1,
NSLog(@"%@",array);此时若再执行该操作系统会crash, 因为数组已经被回收, 如果输出相当于对被回收的数组进行操作,是野指针问题
[per1release];
[per2release];
此时per1和per2的空间都被回收,因为系统识别到他们的引用计数都为0
NSLog(@"arrayCount= %lu",[array retainCount]);
若进行此操作,会crash, 因为array的空间已经被回收
(3), [per1release];
[per2release];
此时per1和per2所指向的空间的引用计数都为1, array所指向的空间的引用计数为1,
[arrayrelease];
此时array所指向的空间被系统回收,per1和per2的空间也都被回收,当集合(数组,字典,集合)空间被回收时,他们会向容器中的每个元素发送一个release消息(对应添加元素时的retain操作),即此时per1和per2的空间都被回收,因为他们收到了release消息,
属性与内存管理(属性与内存管理都是相互关联的) 第二部分,布布扣,bubuko.com
原文地址:http://9178463.blog.51cto.com/9168463/1541390