I would like to take the GCD approach of using shared instances to the next step so I created the following code:
我想采用GCD方法将共享实例用于下一步,因此我创建了以下代码:
@implementation MyClass
static id sharedInstance;
#pragma mark Initialization
+ (instancetype)sharedInstance {
static dispatch_once_t once;
dispatch_once(&once, ^{
sharedInstance = [[self alloc] init];
});
return sharedInstance;
}
- (instancetype)init {
if (sharedInstance) {
return sharedInstance;
}
@synchronized(self) {
self = [super init];
if (self) {
sharedInstance = self;
}
return self;
}
}
@end
I assume the sharedInstance
method seems to be ok but I am unsure about the init method. The reason for creating this is that I don't want people using my SDK, to use the init method, and if they do ... make it bullet proof.
我假设sharedInstance方法似乎没问题,但我不确定init方法。创建这个的原因是我不希望人们使用我的SDK,使用init方法,如果他们这样做...使它成为子弹证明。
3 个解决方案
#1
10
Instead of transparently redirecting calls to init
to the singleton implementation which can cause very confusing behaviour for the users of your SDK, I suggest not allowing to call init at all:
而不是透明地将对init的调用重定向到单例实现,这可能会导致SDK用户的行为非常混乱,我建议不要允许调用init:
+ (instancetype)sharedInstance {
static dispatch_once_t once;
dispatch_once(&once, ^{
sharedInstance = [[self alloc] initPrivate];
});
return sharedInstance;
}
- (instancetype)init {
@throw [NSException exceptionWithName:NSInternalInconsistencyException reason:@"..." userInfo:nil];
}
- (instancetype)initPrivate {
if (self = [super init]) {
...
}
return self;
}
#2
3
I would like to suggest new ways of solving your problem.
我想建议解决问题的新方法。
You can use NS_UNAVAILABLE
in the header file just like this:
您可以在头文件中使用NS_UNAVAILABLE,如下所示:
//Header file
@interface MyClass : NSObject
+ (instancetype)sharedInstance
- (instancetype)init NS_UNAVAILABLE;
//...
@end
In this case init
function will not be available from outside, will not be suggested for autocompletion, and you'll be able to normally use the init
method inside implementation file.
在这种情况下,init函数将不会从外部获得,不会建议自动完成,并且您将能够在实现文件中正常使用init方法。
As you are making a singleton class I would suggest you to make new
method unavailable too by adding this line to the header file:
当你正在创建一个单例类时,我建议你通过在头文件中添加这一行来使新方法不可用:
+ (instancetype)new NS_UNAVAILABLE;
There is also an old way of making methods unavailable (which can be used in header too):
还有一种使方法不可用的旧方法(也可以在标题中使用):
- (instancetype) init __attribute__((unavailable("Use 'sharedInstance' instead of 'init' as this class is singleton.")));
This can be used if you want to prompt some message about unavailability.
如果要提示有关不可用的消息,可以使用此方法。
#3
0
The general opinion is that trying to protect your singleton against that kind of bug is pointless. Whoever calls [[LUIMain alloc] init]
and creates a singleton gets what they deserved.
一般的观点是,试图保护你的单身人士免受这种错误是毫无意义的。无论谁调用[[LUIMain alloc] init]并创建一个单例,他们都得到了他们应得的东西。
And the code that you wrote isn't thread safe anyway. If I call [[LUIMain alloc] init]
while someone else calls sharedInstance, sharedInstance will return a different object than on the next call. (@synchronized (self)
in the init method is pointless, because a second caller will have a different self).
而且你编写的代码无论如何都不是线程安全的。如果我在其他人调用sharedInstance时调用[[LUIMain alloc] init],则sharedInstance将返回与下一次调用不同的对象。 (init方法中的@synchronized(self)是没有意义的,因为第二个调用者将拥有不同的self)。
#1
10
Instead of transparently redirecting calls to init
to the singleton implementation which can cause very confusing behaviour for the users of your SDK, I suggest not allowing to call init at all:
而不是透明地将对init的调用重定向到单例实现,这可能会导致SDK用户的行为非常混乱,我建议不要允许调用init:
+ (instancetype)sharedInstance {
static dispatch_once_t once;
dispatch_once(&once, ^{
sharedInstance = [[self alloc] initPrivate];
});
return sharedInstance;
}
- (instancetype)init {
@throw [NSException exceptionWithName:NSInternalInconsistencyException reason:@"..." userInfo:nil];
}
- (instancetype)initPrivate {
if (self = [super init]) {
...
}
return self;
}
#2
3
I would like to suggest new ways of solving your problem.
我想建议解决问题的新方法。
You can use NS_UNAVAILABLE
in the header file just like this:
您可以在头文件中使用NS_UNAVAILABLE,如下所示:
//Header file
@interface MyClass : NSObject
+ (instancetype)sharedInstance
- (instancetype)init NS_UNAVAILABLE;
//...
@end
In this case init
function will not be available from outside, will not be suggested for autocompletion, and you'll be able to normally use the init
method inside implementation file.
在这种情况下,init函数将不会从外部获得,不会建议自动完成,并且您将能够在实现文件中正常使用init方法。
As you are making a singleton class I would suggest you to make new
method unavailable too by adding this line to the header file:
当你正在创建一个单例类时,我建议你通过在头文件中添加这一行来使新方法不可用:
+ (instancetype)new NS_UNAVAILABLE;
There is also an old way of making methods unavailable (which can be used in header too):
还有一种使方法不可用的旧方法(也可以在标题中使用):
- (instancetype) init __attribute__((unavailable("Use 'sharedInstance' instead of 'init' as this class is singleton.")));
This can be used if you want to prompt some message about unavailability.
如果要提示有关不可用的消息,可以使用此方法。
#3
0
The general opinion is that trying to protect your singleton against that kind of bug is pointless. Whoever calls [[LUIMain alloc] init]
and creates a singleton gets what they deserved.
一般的观点是,试图保护你的单身人士免受这种错误是毫无意义的。无论谁调用[[LUIMain alloc] init]并创建一个单例,他们都得到了他们应得的东西。
And the code that you wrote isn't thread safe anyway. If I call [[LUIMain alloc] init]
while someone else calls sharedInstance, sharedInstance will return a different object than on the next call. (@synchronized (self)
in the init method is pointless, because a second caller will have a different self).
而且你编写的代码无论如何都不是线程安全的。如果我在其他人调用sharedInstance时调用[[LUIMain alloc] init],则sharedInstance将返回与下一次调用不同的对象。 (init方法中的@synchronized(self)是没有意义的,因为第二个调用者将拥有不同的self)。