I'm trying to create a singleton class in Objective-C that will also be consumed in Swift. I'd like the singleton instance to be accessible in Swift as a property.
It appears that Apple does something similar (though not quite a singleton) in NSFileManager
.
@property(class, readonly, strong) NSFileManager *defaultManager;
Ref: https://developer.apple.com/documentation/foundation/nsfilemanager/1409234-defaultmanager
Here's my (simplified) attempt so far:
FOOMyManager.h:
@interface FOOMyManager : NSObject
@property(class, readonly, strong) FOOMyManager *defaultManager;
- (instancetype)init NS_UNAVAILABLE;
@end
FOOMyManager.mm
@implementation FOOMyManager
+ (FOOMyManager *)defaultManager {
static dispatch_once_t s_once = 0;
static FOOMyManager *s_instance = nil;
dispatch_once(&s_once, ^{
s_instance = [[FOOMyManager alloc] initForDefaultManager];
});
return s_instance;
}
- (instancetype)initForDefaultManager {
self = [super init];
return self;
}
@end
I've seen instances of a similar pattern being used to create singletons using
+ (instancetype)defaultManager;
But I'd explicitly like to try and use properties if possible. Is my attempt the "right" way to do this?
Yes, you've got the right principles.
You don't need the strong
, since that's an attribute used for a synthesized setter telling it that it should retain a strong reference to anything passed into the setter. In this case it's not doing anything since class properties are never synthesized automatically, and it's marked as readonly
so strong
wouldn't have any effect anyways.
Your code looks good. dispatch_once
is the preferred way of instantiating a singleton.
As far as any improvements, you can add a message to the unavailable attribute: __attribute__((unavailable("Use FOOMyManager.defaultManager")))
. I wouldn't say it's necessary or adds much since it's clear from the header file what to do, but I'm including it here as an option.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With