1. 在自己实现 便利构造器 时导致每次执行程序都产生空指针异常。代码和原因如下:
+ (UILabel*)labelWithFrame:(CGRect)frame andText:(NSString*)text
{
UILabel *label = [[UILabel alloc] initWithFrame:frame];
label.text = text;
return [label autorelease];
}
@implementation AAAController
- (void)init
{
_label = [UILabel labelWithFrame:CGRectMake(30, 100, 100, 30) andText:@“姓名”];
[self.view addSubview:_label];
}
- (void)dealloc
{
[_label release];
_label = nil;
[super dealloc];
}
@end
想实现一个UILabel的便利构造器,但是每次执行页面切换后都产生空指针异常。
找了很久才找到了原因:
构造器返回的是一个autorelease对象,而当执行了_label = [UILabel labelWithFrame:CGRectMake(30, 100, 100, 30) andText:@“姓名”];之后,_label指向的就是那个autorelease对象,而引用计数却没有加1(此时为1)。此时是危险的,当autorelease对象释放后,_label也就销毁了。而如果autorelease对象前期没有销毁,而是到对象调用了dealloc方法,在方法中执行了[_label release]后,也就相应的将autorelease对象销毁了。之后当autorelease对象想自动销毁时,就导致了程序的崩溃,而且控制台中也不会指出是什么错误。出现这种错误的原因是没有正确的理解便利构造器的使用导致的,所以要好好理解,不能滥用。
以下是改进方法 :
既然知道了导致崩溃的原因(多用了一次release),那就好办了。如下:
方法一: 修改dealloc。即将[_label release]; _label = nil; 删除。
方法二: 将_label = [UILabel labelWithFrame:CGRectMake(30, 100, 100, 30) andText:@“姓名”]; 修改为: self.label = [UILabel labelWithFrame:CGRectMake(30, 100, 100, 30) andText:@“姓名”]; (因为在调用setter方法时引用计数加了1),之后调用了dealloc将 _label release 后,就不会将autorelease对象销毁了。(这种方法更符合编程习惯)。
方法三:把便利构造器修改为:
return [[label retain] autorelease];