【面试题】用assign修饰object类型会怎样?
2017-04-21 本文已影响669人
不上火喝纯净水
问题级别:初级题目
在我们的编码过程中已经养成了使用
assign
修复基本数据类型的良好习惯,我们不会去使用assign
修饰对象类型属性,但是如果用assign
去修复对象类型会怎样呢,你可能会有以下猜测:
- 1.编译会报错;
- 2.编译不报错,运行正常;
- 3.编译不报错,运行不正常;
- ???
开始实验
首先定义一个简单的object
类型,重写dealloc
方便查看对象的释放
@interface TestObject : NSObject
@property (nonatomic, assign) NSInteger age;
@end
@implementation TestObject
- (void)dealloc {
NSLog(@"%s", __FUNCTION__);
}
@end
@interface BasicViewController : BaseViewController
@property (nonatomic ,assign) TestObject *property1;
@end
测试一
- (void)test {
self.property1 = [TestObject new];
self.property1.age = 1;
}
测试二
- (void)test {
TestObject *obj = [TestObject new];
self.property1 = obj;
self.property1.age = 1;
}
实验结果和分析
测试一
结果:测试一会在
self.property1 = [TestObject new];
这一行报出警告,单步调试后发现TestObject
对象会在创建完以后被释放,所以下面self.property1.age = 1
属性赋值将直接引发crash:EXC_BAD_ACCESS,这就是是所谓的野指针。
分析:因为TestObject new
对象创建出来没有任何强指针指向它,所以创建完以后立即会被释放了,这时候self.property1
指针指向的地方已经不可用,所以就成了野指针。
测试二
结果:编译正常没有警告,运行正常也没有报错,但是在
test
方法调用之后如果你再去调用属性property1
同样会引发EXC_BAD_ACCESS。
分析:因为obj
是test
方法内的临时变量,ARC模式下编译器会在test
方法的末尾调用obj release
,所以一旦test
方法执行完毕以后,该临时变量就会被释放,此时self.property1
将变为野指针。由于这种情况下在编译阶段我们的代码都不会有任何的警告,而运行时该属性变为野指针之后,我们在任何地方调用就会引发野指针崩溃,这是很危险的。在快速编码的时候,很有可能由于我们的复制粘贴属性的定义而把object
类型属性用assign
修饰,因为曾经就遇到过同事留下的这种坑,从逻辑上找根本找不错错误,仔细检视代码才发现了这个低级错误