- <span style="font-size:24px;">四,关于语义特性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 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的空间都被回收,因为他们收到</span>
属性与内存管理二
最新推荐文章于 2022-11-07 22:04:17 发布