Objective-C 学习 单例模式

文章目录

单例模式的使用

保证一个类在程序运行期间只创建一个对象,并提供一个全局访问入口。

单例模式有两个关键点:

  1. 只能创建一个对象实例
  2. 提供一个全局访问入口

单例要防止 3 种创建方式

  1. alloc
  2. copy
  3. 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 已是 "已执行" 状态,直接跳过代码块。
    instancetypeObjective-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
相关推荐
yyyyy_abc1 天前
ceph学习笔记
笔记·ceph·学习
晓梦林1 天前
ximai靶场学习笔记
android·笔记·学习
nashane1 天前
HarmonyOS 6学习:外接键盘CapsLock与长截图功能的实战调试与完整解决方案
学习·华为·计算机外设·harmonyos
一口吃俩胖子1 天前
【脉宽调制DCDC功率变换学习笔记021】时域性能准则
笔记·学习
@杰克成1 天前
Java学习30
java·开发语言·学习
三品吉他手会点灯1 天前
C语言学习笔记 - 40.数据类型 - scanf函数的编程规范与非法输入处理
c语言·开发语言·笔记·学习
Bechamz1 天前
大数据开发学习Day36
大数据·学习
ACP广源盛139246256731 天前
iOS 27 开放 AI 生态@ACP#小型化扩展黄金风口,IX8008全面超越 ASM2806,铸就嵌入式 AI 扩展核心
人工智能·嵌入式硬件·macos·ios·计算机外设·objective-c·cocoa
happymaker06261 天前
SpringBoot学习日记——DAY02(SpringBoot整合Swagger3)
java·spring boot·学习