Which one synchronization method to use to ensure a singleton remains a singleton?
+(Foo*)sharedInstance
{
@synchronized(self)
{
if (nil == _shar
If anyone cares, here is another macro for the same thing :)
IMHO, it provides greater flexibility compared to the other variations.
#define SHARED_INSTANCE(...) ({\
static dispatch_once_t pred;\
static id sharedObject;\
dispatch_once(&pred, ^{\
sharedObject = (__VA_ARGS__);\
});\
sharedObject;\
})
Usage, one-line initialization:
+ (instancetype) sharedInstanceOneLine {
return SHARED_INSTANCE( [[self alloc] init] );
}
Usage, multi-line initialization (notice curly braces around the block of code):
+ (instancetype) sharedInstanceMultiLine {
return SHARED_INSTANCE({
NSLog(@"creating shared instance");
CGFloat someValue = 84 / 2.0f;
[[self alloc] initWithSomeValue:someValue]; // no return statement
});
}
Usage in the right part of an assignment:
- (void) someMethod {
MethodPrivateHelper *helper = SHARED_INSTANCE( [[MethodPrivateHelper alloc] init] );
// do smth with the helper
}
// someMethod should not call itself to avoid deadlock, see bbum's answer
This modification utilizes two language features: the GCC compound expressions extension, which is also supported by Clang, and the C99 variadic macros support.
After pre-processing, the output will look like (you can test it yourself by invoking Product > Perform Action > Preprocess "YourClassName.m" in Xcode 5):
+ (instancetype) sharedInstanceOneLine {
return ({
static dispatch_once_t pred;
static id sharedObject;
dispatch_once(&pred, ^{
sharedObject = ( [[self alloc] init] );
});
sharedObject; // this object will be returned from the block
});
}
+ (instancetype) sharedInstanceMultiLine {
return ({
static dispatch_once_t pred;
static id sharedObject;
dispatch_once(&pred, ^{
sharedObject = ({
NSLog(@"creating shared instance");
CGFloat someValue = 84 / 2.0f;
[[self alloc] initWithSomeValue:someValue];
});
});
sharedObject;
});
}
- (void) someMethod {
MethodPrivateHelper *helper = ({
static dispatch_once_t pred;
static id sharedObject;
dispatch_once(&pred, ^{
sharedObject = ( [[MethodPrivateHelper alloc] init] );
});
sharedObject;
});
}