Objective c 返回带有allocWithZone的静态

Objective c 返回带有allocWithZone的静态,objective-c,Objective C,根据iOS编程的Big Nerd Ranch指南中的一个想法,我尝试用以下方式定义singleton对象: @implementation ImageStore static ImageStore *defaultImageStore = nil; - (id)init { if (defaultImageStore) { return defaultImageStore; } self = [super init]; if (self) {

根据iOS编程的Big Nerd Ranch指南中的一个想法,我尝试用以下方式定义singleton对象:

@implementation ImageStore

static ImageStore *defaultImageStore = nil;

- (id)init
{
    if (defaultImageStore) {
        return defaultImageStore;
    }

    self = [super init];
    if (self) {
        dictionary = [[NSMutableDictionary alloc] init];
    }

    NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter];
    [notificationCenter addObserver:self selector:@selector(clearCache) name:UIApplicationDidReceiveMemoryWarningNotification object:nil];

    return self;
}

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

+ (ImageStore *)defaultImageStore
{
    if (!defaultImageStore) {
        defaultImageStore = [[super allocWithZone:NULL] init];
    }
    return defaultImageStore;
}
这很好,但是分析器抱怨allocWithZone,说

将保留计数为+0的对象返回给调用方,调用方预期的保留计数为+1(拥有)


我认为代码只是在欺骗分析器,所发生的一切都是正常的,但是有没有更好的模型来完成我想做的事情呢?

我不在乎这些东西。这是我的模式:

@MyClass的实现

-(id) init { ... } /* normal init */

+(MyClass*) defaultMyClass
{
    static MyClass* theObject = nil;
    @synchronized([MyClass class])  // remove synchronzed block in single threaded app
    {
        if (theObject == nil)
        {
            theObject = [[self alloc] init];
        }
    }
    return theObject;
}
可能的话,您可以将初始化器隐藏在类扩展中,以便有文档证明您不应该使用它

还有GCD方法(下面是从Rob Napier的链接中盗取的),它实际上更加轻量级

+ (id) defaultMyClass
{
    static dispatch_once_t pred;
    static MyClass* theObject = nil;

    dispatch_once(&pred, ^{ theObject = [[self alloc] init]; });
    return theObject;
}

我一直抵制GCD模式,因为在我看来,它看起来不太明显。然而,没有什么不能用评论来修复的!与@synchronized相比,GCD使用的锁更加轻量级,因此这将更快。

正如我在一篇评论中提到的,解决编译器警告非常简单,只需在语句中添加一个retain,这在


旁注:我没有提到这一点,但我正在为iOS开发,发现dispatch_once方法似乎会停止我的应用程序的执行。

考虑到我的方法涉及的额外步骤,你的方法似乎更简单……一般来说,如果你覆盖+alloc,你就做错了。我知道苹果发布的代码解释了如何做到这一点(他们实际上并没有推荐这种模式,只是解释而已)。与Cocoa中的任何其他文档相比,该页面可能让更多的开发人员走上了错误的道路。JeremyP的解决方案是众多解决方案之一。今天最好的(也是苹果在WWDC上推荐的)可能是GCD singleton:苹果似乎至少暗中推荐了我在这里使用的模式,区别在于它们在allocWithZone中调用retain。还有一种新的奇特方式,使用
dispatch_once()
,访问singleton对象,如果你想用GCD来弄脏你的手:)创建一个私有的init方法(
initSingleton
)。然后在
init
中调用
NSAssert()
并返回
nil
。这将确保您不会意外地尝试创建一个唯一的实例,从而将其转化为编程错误(断言)。然而,在大多数情况下,没有必要强制执行唯一性。请看NSNotificationCenter。如果您愿意,您可以自由创建多个中心,甚至有理由这样做(很少,但有时)。正如JeremyP所指出的,这也使得模拟更易于测试。如果不是真的需要,不要强制唯一性。在iOS上,dispatch_once()是正确的解决方案。如果它停止了,那么你有一个错误。我会在某个时候尝试。就目前而言,这是可行的(retain是defaultImageStore的no-op,但它让分析器感到高兴)。我想我在尝试dispatch_一次时,并没有从以前使用的方法中删除所有代码。效果很好。
+ (id)allocWithZone:(NSZone *)zone
{
    return [[self defaultImageStore] retain];
}