假设我们的-init
方法仅调用self
上的消息,为什么在self != nil
消息无效后检查nil
是否常见?
假设我们有一个初始化程序如下:
- (id)init
{
self = [super init];
if (self) {
[self doThis];
[self setFoo:@"Bar"];
}
return self;
}
我们可以写下:
,而不是检查self
- (id)init
{
self = [super init];
[self doThis];
[self setFoo:@"Bar"];
return self;
}
现在,如果出于某种原因[super init]
返回nil
,那么据我所知,该方法的结果没有差异。为什么我们会不断执行此检查?
答案 0 :(得分:7)
您可以向nil发送消息,但无法访问nil的实例变量。您将获得EXC_BAD_ACCESS
例外。
考虑一个具有实例变量的类:
@implementation MyObject {
int instanceVariable;
}
- (id)init {
self = [super init];
instanceVariable = 7;
return self;
}
如果[super init]
在此示例中返回nil会发生什么?
即使您没有访问任何实例变量,如果您不检查self == nil
,其他事情肯定会出错。您可以轻松地泄漏malloc
- 已分配的内存或文件句柄,或者将自己传递给某些不期望为零的方法。
其他答案声称,如果您不检查零,则可以泄漏对象。例如:
@implementation MyObject
@synthesize someProperty; // assume it's an NSObject *
- (id)init {
self = [super init];
[self setSomeProperty:[[NSObject alloc] init]];
return self;
}
即使self
为零,这也不会在ARC下泄露。在手动引用计数(MRC)下,此示例将泄漏self
是否为零,因为没有任何内容可以平衡来自[NSObject alloc]
的+1保留计数。
在MRC下进行此操作的正确方法是:
- (id)init {
self = [super init];
[self setSomeProperty:[[[NSObject alloc] init] autorelease]];
}
或者这个:
- (id)init {
self = [super init];
NSObject *object = [[NSObject alloc] init];
[self setSomeProperty:object];
[object release];
return self;
}
无论self
是否为零,都不会泄漏。
如果你绕过setter方法,就像这样,如果self
为零,你就会崩溃:
- (id)init {
self = [super init];
_someProperty = [[NSObject alloc] init];
return self;
}
答案 1 :(得分:0)
如果[super init]反过来返回nil,那么你最终可能会分配更多永远不会被使用的对象,因为当你返回self时,你将返回nil;所以这些对象不会被释放。