(IOS)单例

概述

单例模式在IOS中的应用非常广泛,如[NSNotificationCenter defaultCenter]、[UIApplication sharedApplication]、[NSFileManager defaultManager]等。

Singleton的宗旨应:该类在程序运行期间有且仅有一个实例

1.单例的优点

单例可以保证系统中该类有且仅有一个实例,所以很便于外界访问.

对于项目中的个别场景的传值,存储状态等等更加方便

2.单例的缺点

一旦创建,对象指针是保存在静态区的,那么在堆区分配空间只有在应用程序终止后才会被释放

单例不能继承

need-to-insert-img

单例的实现

单例的实现重点就是防止在外部调用的时候出现多个不同的实例,我们要从创建的方式入手禁止出现多个不同的实例

防止调用 alloc]init]引起的错误

防止调用 new 引起的错误

防止调用 copy 引起的错误(应该不常用)

防止调用 mutableCopy 引起的错误(应该不常用)

实现方法一

首先需要使用GCD来实现的单例创建,【说明】:dispatch_once函数是GCD中的API,它保证应用程序即使在多线程环境下,也只执行一次。

第一步 (必不可少的)

+ (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];

}

第三步NSCopying

防止copy引起的错误,个人感觉当你的单例类不遵循NSCopying协议,外部调用本身就会出错. 如果不是业务需求不遵循协议,该方法也可以不写 这都是个人观点 不过为了严谨还是写吧

// 防止外部调用copy

- (id)copyWithZone:(nullable NSZone *)zone {

    return [Singleton sharedSingleton];

}

第四步

防止mutableCopy引起的错误,个人感觉当你的单例类不遵循NSMutableCopying协议,外部调用本身就会出错. 如果不是业务需求不遵循协议,该方法也可以不写 这都是个人观点 不过为了严谨还是写吧

// 防止外部调用mutableCopy

- (id)mutableCopyWithZone:(nullable NSZone *)zone {

    return [Singleton sharedSingleton];

}

实现方法二

上面的方法是把其可能出现的初始化方法做了相应的处理来其保证安全性

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

直接在你创建的单例文件的.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;

}

你可能感兴趣的:((IOS)单例)