文章目录
-
- 单例模式的使用
-
- 单例模式有两个关键点:
- [单例要防止 3 种创建方式](#单例要防止 3 种创建方式)
- 完整代码如下:
单例模式的使用
保证一个类在程序运行期间只创建一个对象,并提供一个全局访问入口。
单例模式有两个关键点:
- 只能创建一个对象实例
- 提供一个全局访问入口
单例要防止 3 种创建方式
- alloc
- copy
- mutablecopy
单例模式需要实现一个公共访问的类方法,一般命名为 shared + 类名。在该方法的具体实现方案,是推荐通过dispatch_once 来实现类的实例化。
可以直接通过重写父类的方法,把分配内存的方法变成只执行一次。从根本上实现了单例。
单例模式主要需要重写三个方法
objective-c
+ (instancetype) allocWithZone: (struct _NSZone*) zone
- (id) copyWithZone: (NSZone*) zone
- (id) mutableCopyWithZone: (NSZone*) zone
在 Objective-C 中,调用alloc方法时,底层确实会直接调用allocWithZone: ------alloc本质上是allocWithZone:的 "便捷封装"
objective-c
static MyManager *_instance;
+ (instancetype)sharedInstance {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
_instance = [[super allocWithZone:NULL] init];
});
return _instance;
}
static保存唯一对象, 用dispatch_once 保证只创建一次
如果对象没有创建 -- > 创建
如果对象已经创建 -- > 直接返回
dispatch_once_t类型的onceToken本质是一个状态变量,它存储着「代码块是否已经执行过」的信息:
- 初始状态:
onceToken是一个特殊的默认值(可以理解为 "未执行");- 第一次执行
dispatch_once时:系统会把onceToken的值修改为 "已执行",并执行代码块;- 后续执行
dispatch_once时:系统检测到onceToken已是 "已执行" 状态,直接跳过代码块。
instancetype是 Objective-C 里的一个 返回类型关键字,表示:返回当前类的实例类型。
它主要用于 方法返回对象时,让编译器更准确地知道返回的对象类型。
为什么单例里要写
[[super allocWithZone:NULL] init]而不是
[[self alloc] init]这个其实是 防止递归死循环
在 Objective-C 的单例实现中,我们通常会重写allocWithZone:。如果在sharedInstance里再调用[self alloc],就会触发这个重写的方法,从而产生递归。
objective-c调用 sharedInstance ↓ [[self alloc] init] ↓ alloc ↓ allocWithZone ↓ return [self sharedInstance] ↓ 再次进入 sharedInstance ↓ [[self alloc] init] ↓ allocWithZone ↓ ...
objective-c
+ (instancetype)allocWithZone:(struct _NSZone *)zone {
return [self sharedInstance];
}
- (id)copyWithZone:(NSZone *)zone {
return _instance;
}
- (id)mutableCopyWithZone:(NSZone *)zone {
return _instance;
}
这段代码重写了allocWithZone: copyWithZone: mutableCopyZone: 三种方法, 很好理解,
直接返回唯一对象instance就可以了
完整代码如下:
objective-c
@implementation MyManager
static MyManager *_instance;
+ (instancetype)sharedInstance {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
_instance = [[super allocWithZone:NULL] init];
});
return _instance;
}
+ (instancetype)allocWithZone:(struct _NSZone *)zone {
return [self sharedInstance];
}
- (id)copyWithZone:(NSZone *)zone {
return _instance;
}
- (id)mutableCopyWithZone:(NSZone *)zone {
return _instance;
}
@end