今天偶然看到一篇文章,有所感触,这才发现写了好久的单例竟然并没有写正确,研究了一下,总结如下:
@interface MySingle() <NSCopying, NSMutableCopying>
@end
@implementation MySingle
+ (instancetype)sharedInstance {
static MySingle *single = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
NSLog(@"dispatch_once");
single = [[super allocWithZone:NULL] init];
// 下面代码进行当前类的初始化操作
[single initSelf];
});
NSLog(@"shared called");
return single;
}
// 初始化代码
- (void)initSelf {
self.myName = @"OK";
}
// 不能使用下面这个类进行初始化,否则会陷入死循环,或会使用得外部调用[[xx alloc] init] 会再次触发这个方法
//- (instancetype)init {
// NSLog(@"init called");
// _myName = @"This is it.";
// return self;
//}
+ (instancetype)allocWithZone:(struct _NSZone *)zone {
NSLog(@"allocWithZone");
return [MySingle sharedInstance];
}
- (instancetype)copyWithZone:(NSZone *)zone {
NSLog(@"copyWithZone");
return self;
}
- (instancetype)mutableCopyWithZone:(NSZone *)zone {
NSLog(@"mutableCopyWithZone");
return self;
}
@end
使用时,下面几种方式都能访问到唯一的单例对象,且初始化方法也只会被调用一次,完美,收工。
MySingle *allIN = [[MySingle alloc] init];
NSLog(@"init:%@, name=%@", allIN, allIN.myName);
MySingle *the = [MySingle sharedInstance];
MySingle *copyIt = [the copy];
NSLog(@"c:%@, name=%@", copyIt, copyIt.myName);
NSLog(@"m:%@", [the mutableCopy]);
需要注意的是, 上面sharedInstance中写初始化时使用的是[super allocWithZone], 这里不能写成[self allocWithZone],否则会引发循环。