iOS NSMutable属性声明时为什么不能使用copy

在iOS开发里面我们经常会进行NSMutable(可变类型的类,常用的如NSMutableString,NSMutableArray,NSMutableDictionary,NSMutableData等)属性的声明,在声明时我们都知道要使用strong(强引用)来进行标识,但是很多人不知道为什么不能使用copy来进行标识,下面我们展开讨论一下:

1.为什么不能使用copy:

总所周知,所有的可变类都是继承于非可变类的,属于可变类的子类,拿NSMutableString类来举例,大家进入到NSMutableString类的.h文件可以看到它是继承于NSString类的,而且NSMutableString类并没有重写NSString类的copy方法,所以我们如果声明NSMutableString类属性时使用了copy进行标识,在我们对这个属性进行赋值时,调用的其实是NSString类的copy方法,拿到的实例对象其实是一个NSString的实例,而不是一个NSMutableString的实例,下面使用代码给大家验证一下:

 


从输出结果可以看到tempStr是一个NSMutableString对象,使用strong修饰声明的属性str只是对tempStr对象添加了一个引用计数,并没有产生新的对象实例,所以tempStr和str的class方法其实调用的是同一个对象的方法,所以输出的结果是一样的。而使用copy修饰声明的属性mstr在被赋值时,会调用tempStr对象的copy方法产生一个新的对象,而且从输出结果可以看到这个对象是NSString对象。

综上所述,NSMutable属性声明时不能使用copy进行修饰是因为NSMutable类并没有重写非可变类的copy方法,给属性赋值时,调用的是父类的copy方法,得到的对象是一个非可变对象。

2.使用了copy会怎样:

由于给对象赋值时得到的对象是非可变对象,所以我们使用该属性调用可变对象的特有方法时程序会奔溃(因为对象根本响应不了该方法),下面我们同样适用代码给大家验证一下:


tempStr对象和str属性的replaceCharactersInRange方法均执行成功,但是程序运行到[self.mstr replaceCharactersInRange:NSMakeRange(0, 1) withString:@""]这句代码时奔溃了,所以这个问题对程序的影响还是很大的,而且这个的bug很难被找出来,所以在声明NSMutable属性时一定要多加注意。


猜你喜欢

转载自blog.csdn.net/guozirong123/article/details/80781566