iOS单例模式的正确写法

单例模式很常见,但是,能真正把单利模式写对的却很少。
在iOS中,一般我们都是用官方推荐的写法来写单例:

+ (instancetype)sharedInstance {
    static URLManager * ins = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        ins = [[URLManager alloc] init];
    });
    return ins;
}

URLManager* a = [URLManager sharedInstance];
接下来,可以用 a 这个单例来干很多事情了,看起来没有问题。在很多实际的项目中,很多人也的确是这么做的。

可是,谁能保证所有人都会使用 sharedInstance 方法来创建对象?而一旦有人用 alloc,new 等来创建对象,这就不是单例了。
例如:

    URLManager* a = [URLManager sharedInstance];
    URLManager* b = [[URLManager alloc] init];
    URLManager* c = [URLManager new];

查看 a、b、c :

image

可以看到,a、b、c 不是同一个对象,而所谓单例,就是不管我用何种方法创建对象,都必须是同一个
所以,单例模式,绝不是一个 sharedInstance 就够了。

解决方案 一
那么如何避免这种问题呢?我们知道:
在对象创建的时候,无论是 alloc 还是 new,都会调用到 allocWithZone: 方法;
使用拷贝创建对象时,会调用 copyWithZone:,mutableCopyWithZone:方法;
那么,重写这些方法,就可以让创建的对象唯一。

+ (instancetype)sharedInstance {
    static URLManager * 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];
}

再运行,看一看a、b、c:


image

都是同一个对象!大功告成!

解决方案 二
此外,还有一种方法,就是直接禁用掉 alloc、new 、copy等方法:

+(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'")));

如此,在调用这些方法时就会报错,提示使用 sharedInstance 方法:


image

以此,也可以达到单例模式的要求,始终只有一个对象。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 1.ios高性能编程 (1).内层 最小的内层平均值和峰值(2).耗电量 高效的算法和数据结构(3).初始化时...
    欧辰_OSR阅读 29,712评论 8 265
  • Swift1> Swift和OC的区别1.1> Swift没有地址/指针的概念1.2> 泛型1.3> 类型严谨 对...
    cosWriter阅读 11,161评论 1 32
  • 设计模式概述 在学习面向对象七大设计原则时需要注意以下几点:a) 高内聚、低耦合和单一职能的“冲突”实际上,这两者...
    彦帧阅读 3,804评论 0 14
  • 昨天看到吴晓波的一句话“阅读能不能改变我们的生活我不知道,但阅读一定能趣味我们的人生,新岁即至,岁月仍在激荡,让我...
    今天安好阅读 165评论 0 0
  • 垃圾在翻滚,树叶在咆哮,车车在减少,忽面而来的雨水打在脸上。 红灯停了,商场来来往往的人儿也消失了,除了那遥远的横...
    木兮_7340阅读 136评论 0 0