单例是什么以及作用就不单独解释了
强单例
iOS 中常见的单例模式有两种方式:
+(instancetype)sharedInstance{
static dispatch_once_t onceToken;
static Singleton *instance;
dispatch_once(&onceToken, ^{
if(!instance){
instance = [[Singleton alloc] init];
}
});
return instance;
}
+(instancetype)sharedInstance{
static Singleton *instance = nil;
@synchronized (self) {
if(!instance){
instance =[[Singleton alloc] init];
}
}
return instance;
}
这也是到处都能查到的调用GCD 或互斥锁生成的单例
这种单例需要考虑的情况是如果别人直接调用 alloc 和init 方法,便生成了新的类实例
为了防止别人通过这种方式获得实例,可以使用一种更为标准的单例,以GCD 为例:
+(instancetype)sharedInstance{
static dispatch_once_t onceToken;
static Singleton *instance;
dispatch_once(&onceToken, ^{
if(!instance){
instance = [[super allocWithZone:NULL] init];
}
});
return instance;
}
+(instancetype)allocWithZone:(struct _NSZone *)zone{
return [self sharedInstance];
}
- 如果考虑 NSCopying 和 NSMutableCopy 协议时,还需要覆写对应方法返回单例。
调用 alloc 方法时,可以理解为以下形式(这里可以参考 10栋208)
+ (id) alloc{
return [self allocWithZone:NULL];
}
当别人想通过 alloc 方法获取实例时,通过覆写的方法便会返回单例
而单例的创建中调用 [super allocWithZone:NULL] 是为了绕开覆写的方法,避免死循环
弱单例
通过之前的方式生成的单例对象会一直占用内存到应用程序结束,弱单例的出现便是考虑到这点,使用方式同强单例,不同点在于使用时需要对单例进行强引用,当引用计数降到0时,单例便被释放,弱单例的生成方式如下
+(instancetype)weakSharedInstance{
static __weak Singleton *weakInstance;
Singleton *instance = weakInstance;
@synchronized (self) {
if(!instance){
instance =[[Singleton alloc] init];
weakInstance = instance;
}
}
return instance;
}
(以下为臆测,如有错误请指正)
这里利用了 ARC 机制,instance 为局部变量,返回时由自动释放池持有,使用时需要通过强引用持有这个单例,当其他对象不再持有(即不再使用时),自动释放池便会释放单例,弱引用weakInstance 置nil,下次需要使用单例时再重新创建。通过这种方式避免了单例不使用时占用内存的情况。
参考:
网友评论