iOS 单例模式防止调用alloc 、new 、copy

一般情况下我们单利调用 单利方法就可以构建,但是当调用alloc,new,copy并不能保证单利,如何防止在外部调用的时候出现多个不同的实例呢。

1.通过创建方式去实现

首先需要使用GCD来实现的单例创建

+ (instancetype)sharedSingleton {
    static Singleton *_sharedSingleton = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        //不能再使用alloc方法
        //因为已经重写了allocWithZone方法,所以这里要调用父类的分配空间的方法
        _sharedSingleton = [[super allocWithZone:NULL] init];
    });
    return _sharedSingleton;
}

防止alloc] init] 和new引起的错误,因为alloc] init] 和 new 实际是一样的工作原理.都是执行了下面方法

// 防止外部调用alloc 或者 new
+ (instancetype)allocWithZone:(struct _NSZone *)zone {
    return [Singleton sharedSingleton];
}

防止copy引起的错误,个人感觉当你的单例类不遵循NSCopying协议,外部调用本身就会出错.

// 防止外部调用copy
- (id)copyWithZone:(nullable NSZone *)zone {
    return [Singleton sharedSingleton];
}

防止mutableCopy引起的错误,个人感觉当你的单例类不遵循NSMutableCopying协议,外部调用本身就会出错.

// 防止外部调用mutableCopy
- (id)mutableCopyWithZone:(nullable NSZone *)zone {
    return [Singleton sharedSingleton];
}

2.通过.h禁止外部调用控制

其实我们可以在不做处理的情况下 禁止外部调用岂不是更简单 。 个人感觉该方法也很不错而且一些成熟的第三方中的单例中也有使用该方法的

直接在你创建的单例文件的.h文件中加入代码

- (instancetype)init NS_UNAVAILABLE;
+ (instancetype)new NS_UNAVAILABLE;
- (id)copy NS_UNAVAILABLE; // 没有遵循协议可以不写
- (id)mutableCopy NS_UNAVAILABLE; // 没有遵循协议可以不写

.m文件实现一个方法即可,上面方式的其他方法就不要写了

// 跟上面的方法实现有一点不同
+ (instancetype)sharedSingleton {
    static Singleton *_sharedSingleton = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
          // 要使用self来调用
        _sharedSingleton = [[self alloc] init];
    });
    return _sharedSingleton;
}