- 在iOS OC中,用官方推荐的写法来写单例:
+ (instancetype)sharedInstance {
static DBManager * ins = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
ins = [[DBManager alloc] init];
});
return ins;
}
DBManager *a = [DBManager sharedInstance];
接下来,可以用 a 这个单例来干很多事情了,看起来没有问题。在很多实际的项目中,很多人也的确是这么做的。
但是,这种方式若用 alloc,new 等来创建对象,此时新建的对象就不是原来的单一对象了,而是新的
// a,b,c 3个对象的地址是不同的:
DBManager* a = [DBManager sharedInstance];
DBManager* b = [[DBManager alloc] init];
DBManager* c = [DBManager new];
我们可以知道,Apple有很多的单例对象也是这样的,比如 NSFileManager
根据需要,我们可以采用这种方式,这种方式或许不叫单例,而只是提供一个公用对象,也可以像下面,写一个真正的单例
创建一个真正的单例,就是不管我用何种方法创建对象,都必须是同一个:
+ (instancetype)sharedInstance {
static DBManager * ins = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
ins = [[super allocWithZone:nil] init];
});
return ins;
}
+(id)allocWithZone:(NSZone *)zone{
return [self sharedInstance];
}
-(id)copyWithZone:(NSZone *)zone{
return [[self class] sharedInstance];
}
-(id)mutableCopyWithZone:(NSZone *)zone{
return [[self class] sharedInstance];
}
这些就都是同一个对象了:
DBManager *a = [DBManager sharedInstance];
DBManager *b = [[DBManager alloc]init];
DBManager *c = [DBManager new];
DBManager *d = [a copy];
ps: 也可以禁用掉别的对象生成方式:
+(instancetype) alloc __attribute__((unavailable("replace with 'sharedInstance'")));
+(instancetype) new __attribute__((unavailable("replace with 'sharedInstance'")));
-(instancetype) copy __attribute__((unavailable("replace with 'sharedInstance'")));
-(instancetype) mutableCopy __attribute__((unavailable("replace with 'sharedInstance'")));
swift 单例写法
let是线程安全的
方法一
如果没有特别的需求,我建议都使用这样的方式实现单例。
class Manager {
static let sharedInstance = Manager()
}
方法二
private let sharedInstance = Manager()
class Manager {
class var sharedManager: Manager {
return sharedInstance
}
}