- 若选择单例,必须有的三个想法
可以被全局访问
不会被释放
创建过程只执行1次
- 伪单例 和 完整单例
伪单例
1、 获取单例对象的方法
+ (DataHandle *)sharedDataHandle; // 创建单例对象的方法。类方法 命名规则: shared + 类名
2、 方法的实现
// 因为实例是全局的 因此要定义为全局变量,且需要存储在静态区,不释放。不能存储在栈区。
static DataHandle *handle = nil;
// 伪单例 和 完整的单例。 以及线程的安全。
// 一般使用伪单例就足够了 每次都用 sharedDataHandle 创建对象。
+ (DataHandle *)sharedDataHandle
{
// 添加同步锁,一次只能一个线程访问。如果有多个线程访问,等待。一个访问结束后下一个。
@synchronized(self){
if (nil == handle) {
handle = [[DataHadle alloc] init];
}
}
return handle;
}
完整的单例:不仅要求我们通过方法获取的对象是单例,如果有 对该对象进行copy mutableCopy copyWithZone 等操作
- 完整的单例要做到四个方面:
(1).为单例对象实现一个静态实例,然后设置成nil,
(2).构造方法检查静态实例是否为nil,是则新建并返回一个实例,
(3).重写allocWithZone方法,用来保证其他人直接使用alloc和init试图获得一个新实例的时候不会产生一个新实例,
(4).适当实现copyWithZone,retain,retainCount,release和autorelease 等方法
1.同上
2.方法的实现:
@synchronized(self){
if (nil == handle) {
handle = [[super allocWithZone:nil] init]; // 避免死循环
// 如果 在单例类里面重写了 allocWithZone 方法 ,在创建单例对象时 使用 [[DataHandle alloc] init] 创建,会死循环。
}
}
return handle;
- 重写 allocWithZone copy mutableCopy copyWithZone
防止外界拷贝造成多个实例, 保证实例的唯一性。
注意:如果自己重写了 allocWithZone 就不要再调用自身的 alloc 方法,否则会出现死循环。
+ (instancetype)allocWithZone:(struct _NSZone *)zone
{
return [DataHandle sharedDataHandle];
}
- (id)copy
{
return self;
}
- (id)mutableCopy
{
return self;
}
+ (id)copyWithZone:(struct _NSZone *)zone
{
return self;
}
4、 重写 alloc retain release autorelease retainCount
+ (instancetype)alloc
{
return [DataHandle sharedDataHandle];
}
// 因为只有一个实例, 一直不释放,所以不增加引用计数。无意义。
- (instancetype)retain
{
return self;
}
- (oneway void)release
{
// nothing
}
- (instancetype)autorelease
{
return self;
}
- (NSUInteger)retainCount
{
return NSUIntegerMax; // 返回整形最大值。
}
——-------------------------------------
实例实现夜间模式
首先创建单例,继承NSObject,并且创建一个便利构造器方法(DKNightVersionManager很有名的)
// @Escapeplan
+ (DKNightVersionManager *) sharedNightVersionManager {
static DKNightVersionManager *instance = nil;
@synchronized(self) {
if (instance == nil) {
instance =[ [DKNightVersionManager alloc] init];
}
}
return instance;
}
// 更准确的写法
+ (DKNightVersionManager *)sharedNightVersionManager {
static dispatch_once_t once;
static DKNightVersionManager *instance;
dispatch_once(&once, ^{
instance = [self new];
});
return instance;
}
创建一个BOOL观察状态
//添加一个bool属性,判断是日间还是夜间
@property (nonatomic, assign) BOOL type
switch 创建并添加方法
UISwitch *mySwitch = [UISwitch new];
// 添加到视图上
[mySwitch addTarget: self action: @selector(judgeDayOrNight) forControlEvents:UIControlEventValueChanged];
在这VC中执行如下操作
- (void)(judgeDayOrNight {
DKNightVersionManager *instance = [DKNightVersionManager sharedNightVersionManager];
if (mySwitch.on) {
instance.type = YES;
//改变为夜间的颜色
} else {
instance.type = NO;
//改变成日间的颜色
}
}
在其他VC中应有相应的改变
// 引单例的头文件
- (void)viewDidLoad {
DKNightVersionManager *instance = [DKNightVersionManager sharedNightVersionManager];
if (instance.type) {
//改变成夜间模式
} else {
//改变成日间模式
}
}