2012-08-15 45 views
6

BNRItemStore是一个单例,我很困惑为什么super allocWithZone:必须被调用而不是普通的旧的super alloc。然后覆盖alloc而不是allocWithZone使用allocWithZone创建一个单例:

#import "BNRItemStore.h" 

@implementation BNRItemStore 

+(BNRItemStore *)sharedStore { 
    static BNRItemStore *sharedStore = nil; 

    if (!sharedStore) 
     sharedStore = [[super allocWithZone: nil] init]; 

    return sharedStore; 
} 

+(id)allocWithZone:(NSZone *)zone { 
    return [self sharedStore]; 
} 

@end 

回答

10

[super alloc]将通过调用allocWithZone:,您已覆盖做别的事情。为了实际获得超类的实现allocWithZone:(这是你想要的),而不是被覆盖的版本,你必须明确地发送allocWithZone:

super关键字表示与self相同的对象;它只是告诉方法调度机制开始在超类而不是当前类中寻找相应的方法。

因此,[super alloc]将上升到超类,并得到执行那里,它看起来像:

+ (id) alloc 
{ 
    return [self allocWithZone:NULL]; 
} 

这里,self仍然是你的自定义类,因此,你的覆盖allocWithZone:运行,这会将您的程序发送到无限循环。

+0

难倒了,这是在ObjC入门课程的一个微妙的一面,所以如果你有关于我的答案的问题,我很乐意澄清。 – 2012-08-15 01:29:06

+0

谢谢!我有一个问题。如果我删除了重写allocWithZone的方法:是否可以调用super alloc而不是super allocWithZone:在sharedStore中? – stumped 2012-08-15 01:31:35

+0

是的。覆盖'allocWithZone:'的原因是限制这个类的任何用户创建另一个实例。他们会直接调用alloc(或可能是'allocWithZone:';而不是分配一个新的实例,而是返回现有的实例,这是使这个类成为单例的关键部分 – 2012-08-15 01:35:53

3

从苹果公司的documentation

这种方法存在的历史原因;内存区不再是Objective-C使用的 。

相关问题