iOS 你不知道的新鲜事iOS 开发成长中心iOS开发

iOS 中的强单例和弱单例

2017-08-07  本文已影响424人  4a3c61ff974e

单例是什么以及作用就不单独解释了

强单例

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];
}
+ (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,下次需要使用单例时再重新创建。通过这种方式避免了单例不使用时占用内存的情况。

参考:

上一篇 下一篇

猜你喜欢

热点阅读