单例全局唯一性
程序员文章站
2022-07-14 08:06:34
...
如何实现单例全局唯一
很多人看到标题可能会不屑一顾,单例本身就是全局唯一的啊,这也是我这几年一直坚信的从未怀疑的事实????
static Manager *manager = nil;
+ (instancetype)managerCenter {
static dispatch_once_t predicate;
dispatch_once(&predicate, ^{
manager = [[Manager alloc] init];
});
return manager;
}
相信大部分人都是这一种写法,简单直观又明了。但是假设一个在多人合作的项目里,同事B在不知Manager是单例的情况下调用了[Manager alloc]init;
验证一下就会发现这是一个新的对象,我写了**年的居然到最近才发现这个事实????。
那么如何保证无论使用者如何调用都保证单例的全局唯一
方法1:
使用NSAssert
重现alloc方法如
+ (instancetype)alloc
{
NSAssert(NO, @"请使用shared方法");
return nil;
}
这种方法可以有效的提醒其他的程序员这是一个单例,但是只有等到运行时才能提示。
方法2:
static Manager *defaultManager = nil;
+ (Manager *)defaultManager
{
@synchronized(self) //保证线程安全
{
if (defaultManager == nil)
{
defaultManager = [[self alloc] init];
}
}
return defaultManager;
}
+ (id)allocWithZone:(NSZone *)zone
{
@synchronized(self)
{
if (defaultManager == nil)
{
return [super allocWithZone:zone];
}
}
return defaultManager;
}
- (id)init
{
Class class = [self class];
@synchronized(class)
{
if (defaultManager == nil)
{
if (self = [super init])
{
defaultManager = self; //使Manager赋值初始化
}
}
}
return defaultManager;
}
运行如下测试代码,可以发现打印的结果都是一致的。
Manager *m1 = [Manager defaultManager];
NSLog(@"m1 : %p", m1);
Manager *m2 = [[Manager alloc]init];
NSLog(@"m2 : %p", m2);
Manager *m3 = [Manager alloc];
NSLog(@"m3 : %p", m3);
Manager *m4 = [Manager new];
NSLog(@"m4 : %p", m4);
关于@synchronized
使用了线程锁详情参见这里 还有这里
这是我iOS遇坑填坑系列中的一篇,如果有大神发现其中的错误请指正,谢谢!
上一篇: 单例模式(确保对象的唯一性)
下一篇: 数据库唯一性约束