1.引
看一段代码
@interface ViewController ()
@property (nonatomic, copy) NSMutableArray *array;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.array = [NSMutableArray array];
[self.array addObject:@"A"];
@end
结果是系统崩溃,后台打印如下错误信息
2018-04-03 15:02:11.238078+0800 iOS[55183:3743941] -[__NSArray0 addObject:]: unrecognized selector sent to instance 0x6040000065a0
2018-04-03 15:02:11.242691+0800 iOS[55183:3743941] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSArray0 addObject:]: unrecognized selector sent to instance 0x6040000065a0'
这个时候如果将array的初始化方法换成
_array = [NSMutableArray array];
运行正常!
2.原因
不讨论copy和strong的区别,百度可以找到一堆,这里只讨论为什么_array不会崩溃!那貌似标题就得改了。。。
在Java里有一个名词叫Bean,对属性生成setter和getter方法之后,这个变量就是一个bean;
回到OC,系统会自动对@property变量生成setter和getter方法,也就是一个bean,它们其实都是在这个变量的基础上封了一层,我们用到懒加载的时候是要对自己的变量自己写读和写的方法
//getter:
- (NSMutableArray *)array {
NSLog("%@", _array);
return _array;
}
//setter:
- (void)setArray:(NSMutableArray *)newValue {
_array = newValue;
}
用到的就是_array.所以直接使用_array是绕过了getter方法和setter方法,那么_array是直接操作了实例变量;
再来,系统申明一个变量的时候默认是__strong也就是说_array是一个被strong修饰的变量,并不是copy修饰的。
id objc = [NSObject new];
//完整的代码是这个
id __strong objc = [NSObject new];
理解了上面的原因之后,总结一下,self.array是使用了系统的setter和getter,所以array初始化的时候,将[NSMutableArray array]这个对象copy了一下,变成了[array copy]传给了_array,NSArray是NSMutableArray的父类,没有addObject的方法,所以崩溃了~
3. 解决
最好的方法是,将修饰符
@property (nonatomic, strong) NSMutableArray *array;
网友评论