Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Apple singleton code warning... again

I have this singleton code in an app, which I update now and then. While I took the Apple reference code, I've had to update it once or twice since clang was complaining and Apple updated it in response. Today I tried analyzing with Xcode 4.6 and I get a warning again, although Apple hasn't updated in two years. I really can't understand how they can't get a singleton coded in a way that static analyzers will not complain. And it's not like they can't change the static analyzer to accommodate their code if they feel their reference code is right. But back to the code, I have this class:

@implementation MySingleton

static MySingleton *sSharedSingleton = nil;

+ (MySingleton *)sharedSingleton 
{
    if (sSharedSingleton == nil)
    {
        sSharedSingleton = [[super allocWithZone:NULL] init];
    }
    return sSharedSingleton;    
}

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

- (id)copyWithZone:(NSZone *)zone
{
    return self;
}

- (id)retain
{
    return self;
}

- (unsigned)retainCount
{
    return NSUIntegerMax;  //denotes an object that cannot be released
}

- (oneway void)release
{
    //do nothing
}

- (id)autorelease
{
    return self;
}

@end

As far as I can tell, it is exactly the reference from https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/CocoaFundamentals/CocoaObjects/CocoaObjects.html

Clang is complaining about the allocWithZone implementation's return line with the warning:

Object with a +0 retain count returned to caller where a +1 (owning) retain count is expected

I assume we get that because we are overwriting retain. Who do you think is correct, clang or the reference code? Should I just change the code to suppress the message (e.g. avoid overwriting retain) and forget about it?

like image 804
Ecuador Avatar asked Oct 06 '22 04:10

Ecuador


1 Answers

That example is outdated, especially so with introduction of ARC and GCD, mostly, you only need this

+ (DSSingleton *)sharedInstance
{
    static DSSingleton *sharedInstance;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        sharedInstance = [DSSingleton new];
    });

    return sharedInstance;
}

Xcode has great code snippet for that inner part - just type dispatch_once and look for autocomplete

like image 82
Dmitry Shevchenko Avatar answered Oct 10 '22 03:10

Dmitry Shevchenko