mat*_*atm 16 singleton objective-c
我在Obj-C中阅读了一些关于单身人士的惊人资源:
但是这些资源都没有明确地解决init
方法概念,而且仍然是Obj-C的新手我很困惑应该如何实现它.
到目前为止,我知道init
在Obj-C中不能使用私有,因为它不提供真正的私有方法......所以用户可以调用[[MyClass alloc] init]
而不是使用我的[MyClass sharedInstance]
.
我还有什么其他选择?我相信我也应该处理我的单例的子类化方案.
Mec*_*han 25
好吧,一个简单的方法init
就是不要写一个让它调用默认的NSObject实现(只返回self
).然后,对于您的sharedInstance
函数,定义并调用一个私有函数,在您实例化单例时执行类似init的工作.(这可以避免用户意外重新初始化您的单身人士.)
然而!!!主要问题是alloc
用户调用您的代码!为此,我个人推荐Apple的覆盖路线allocWithZone:
......
+ (id)allocWithZone:(NSZone *)zone
{
return [[self sharedInstance] retain];
}
Run Code Online (Sandbox Code Playgroud)
这意味着用户仍然会获得您的单例实例,并且他们可能会错误地使用它们,就像它们分配它一样,并且安全地释放它一次,因为这个自定义alloc对单例执行保留.(注意:alloc
调用allocWithZone:
并不需要单独覆盖.)
希望有所帮助!如果您想了解更多信息,请告诉我们
编辑:扩大答案提供示例和更多细节 -
考虑到Catfish_Man的答案,创建一个防弹单体通常并不重要,而只是在你的标题/文档中写一些合理的注释并放入assert
.
但是,在我的情况下,我想要一个线程安全的延迟加载单例 - 也就是说,在需要使用它之前它不会被分配,而不是在应用程序启动时自动分配.在学会了如何安全地做到这一点之后,我想我也可以一路走下去.
编辑#2:我现在使用GCD dispatch_once(...)
进行线程安全的方法,在应用程序的生命周期内只分配一个单例对象.请参阅Apple Docs:GCD dispatch_once.我还是allocWithZone:
从Apple的旧单例示例中添加了覆盖位,并添加了一个名为的私有init,以singletonInit
防止意外被多次调用:
//Hidden/Private initialization
-(void)singletonInit
{
//your init code goes here
}
static HSCloudManager * sharedInstance = nil;
+ (HSCloudManager *) sharedManager {
static dispatch_once_t dispatchOncePredicate = 0;
dispatch_once(&dispatchOncePredicate, ^{
sharedInstance = [[super allocWithZone:NULL] init];
[sharedInstance singletonInit];//Only place you should call singletonInit
});
return sharedInstance;
}
+ (id) allocWithZone:(NSZone *)zone {
//If coder misunderstands this is a singleton, behave properly with
// ref count +1 on alloc anyway, and still return singleton!
return [[HSCloudManager sharedManager] retain];
}
Run Code Online (Sandbox Code Playgroud)
HSCloudManager
子类NSObject
,并且不会覆盖init
只留下默认实现NSObject
,根据Apple的文档只返回self.这意味着[[HSCloudManager alloc] init]
相同[[[HSCloud Manager sharedManager] retain] self]
,使得混淆用户和多线程应用程序都可以安全地作为延迟加载单例.
至于你对用户子类化子单元的关注,我会说清楚地评论/记录它.任何盲人继承而没有在课堂上阅读的人都在寻求痛苦!
编辑#3: 对于ARC兼容性,只需从allocWithZone:
覆盖中删除保留部分,但保留覆盖.
归档时间: |
|
查看次数: |
7363 次 |
最近记录: |