iOS 中的强单例和弱单例

作者: 4a3c61ff974e | 来源:发表于2017-08-07 15:55 被阅读424次

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

    强单例

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

    参考:

    相关文章

      网友评论

      • 72行代码:能不能解释下,为什么没有人调用的时候,这个弱单例会销毁呢

      本文标题:iOS 中的强单例和弱单例

      本文链接:https://www.haomeiwen.com/subject/ookalxtx.html