单例对象的创建方式
单例.h 文件的实现
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@interface NBNetworkTools : NSObject
// 创建单例对象
+ (instancetype)sharedInstance;
// 销毁单例对象
- (void)dellocInstance;
// 用户名
@property (nonatomic,copy) NSString *username;
// 密码
@property (nonatomic,copy) NSString *password;
@end
NS_ASSUME_NONNULL_END
单例的.m 文件的实现
#import "NBNetworkTools.h"
@implementation NBNetworkTools
static NBNetworkTools *sharedInstance = nil;
static dispatch_once_t onceToken;
+ (instancetype)sharedInstance {
dispatch_once(&onceToken, ^{
// 使用super 调用父类等 allocWithZone,避免循环引用
// 因为重写了 allocWithZone 返回的是 [self sharedInstance], 如果调用了 [self allocWithZone], 就会出现循环调用的问题,规避循环引用使用 super 进行初始化
sharedInstance = [[super allocWithZone:NULL]init];
});
return sharedInstance;
}
// 【必不可少】重写 allocWithZone 方法
// 因为不使用 sharedInstance 进行创建对象的情况,也是有可能的
// 比如使用 alloc 进行创建, alloc 会调用 allocWithZone ,所以重写 allocWithZone,在内部手动调用 [self sharedInstance];
+ (instancetype)allocWithZone:(struct _NSZone *)zone {
return [self sharedInstance];
}
// 【必不可少】当单例被 copy
// 外界有可能会对当前实例进行copy操作来创建一个对象,要保证一个对象在App生命周期内永远只能被创建一次,我们还需要重写 copyWithZone 方法
// 直接将 self 返回就可以了
- (id)copyWithZone:(nullable NSZone *)zone {
return self;
}
// 销毁单例对象
- (void)dellocInstance {
// 设置为0,GCD会认为它从未执行过,这样才能保证下次调用 shareInstance 的时候,再次创建对象
onceToken = 0;
sharedInstance = nil;
}
单例对象的销毁【GCD创建的方式】
使用单例对象的时候,如果我们暂时不用这个对象,同时想释放单例占用的内存空间,所以我们需要把它销毁掉,用的时候在创建出来,那怎么做呢?
上面的代码是包含这部分功能的,操作的方式就是在销毁的方法里面:把 onceToken = 0; 设置为0,此时我们的GCD就会认为这个block没有执行过,就会再次执行Block内的代码
- 可以通过打印观察 onceToken 的值的变化,就可以发现了
- 下面是销毁的代码
// 销毁单例对象
- (void)dellocInstance {
// 设置为0,GCD会认为它从未执行过,这样才能保证下次调用 shareInstance 的时候,再次创建对象
onceToken = 0;
sharedInstance = nil;
}
参考:
iOS单例模式对象的创建及销毁