【iOS】MRC下的单例模式批量创建单例

单例模式的介绍和ARC下的单例请见这篇:【iOS】单例模式

目录

    • 关闭ARC环境
    • MRC下的单例
    • ARC下的单例
    • 批量创建单例
    • Demo


关闭ARC环境

首先关闭ARC环境,即打开MRC:

在这里插入图片描述
或是指定某特定目标文件为非ARC环境:

在这里插入图片描述
双击某个类文件,指定为ARC环境,输入-fobjc-arc,指定为MRC环境,输入-fno-objc-arc

MRC下的单例

MRC下,我们就需要手动释放资源,通过重写一些与资源创建与释放相关的方法,以保证单例对象的唯一。

SingletonByMRC.h

@interface SingletonByMRC : NSObject
+ (instancetype)sharedSingletonByMRC;
@end

SingletonByMRC.m

@implementation SingletonByMRCstatic SingletonByMRC* instanceVariable = nil;/*alloc方法内部会调用allocWithZone:参数zone时系统分配给App的内存*/
+ (instancetype)allocWithZone:(struct _NSZone *)zone {if (!instanceVariable) {static dispatch_once_t onceToken;dispatch_once(&onceToken, ^{  // 安全(这段代码只会被调用一次)instanceVariable = [super allocWithZone: zone];});}return instanceVariable;
}- (oneway void)release {//  allocWithZone中使用了GCD命令创建对象的代码只执行一次(单例),如果被释放则无法再创建//  重写release方法,替换为空操作,防止instanceVariable被释放
}//  重写retain方法
- (instancetype)retain {return self;
}//  重写retainCount锁定引用计数
- (NSUInteger)retainCount {return 1;
}//  重写init方法,防止单例所拥有的属性值被重置
//  让初始化的方法只能执行一次,自然属性值就没有机会被重置
- (instancetype)init {static dispatch_once_t onceToken;dispatch_once(&onceToken, ^{instanceVariable = [super init];});return instanceVariable;
}//  仿造系统的单例创建方式,提供类方法
+ (nonnull instancetype)sharedSingletonByMRC {// 由于我们已经重写了init方法保证了单例对象的唯一了,所以这里直接调用init方法即可。return [[self alloc] init];
}@end

ARC下的单例

与MRC的主要区别就是不用再手动去释放资源了。

SingletonByARC.m

#import "SingletonByARC.h"@implementation SingletonByARCstatic SingletonByARC* insVar = nil;+ (instancetype)allocWithZone:(struct _NSZone *)zone {if (!insVar) {static dispatch_once_t onceToken;dispatch_once(&onceToken, ^{insVar = [super allocWithZone: zone];});}return insVar;
}- (instancetype)init {static dispatch_once_t onceToken;dispatch_once(&onceToken, ^{insVar = [super init];});return insVar;
}+ (instancetype)sharedInstance {return [[self alloc] init];
}@end

批量创建单例

如果一个项目中需要多个单例,总不能把上面的代码一个一个复制粘贴再改改就完事了吧?那未免也太麻烦了。
我们可以利用快速且简单地创建单例。

首先先说下一些关于宏的知识:

  • 使用#define关键字来定义宏
  • 宏定义只能是单行的,不能换行

那现在来讨论下一些疑惑吧,你说宏只能单行,可是创建单例的代码可是有很多行呀!还有我们如何做到自定义类方法名(就是 sharedXXX )?我们来介绍下宏下的两个特殊符号:

符号作用
\用来转译换行符,即屏蔽换行符
##将两个相邻的标记(token)连接为一个单独的标记

简言之,就是\用于取消换行,##用于连接。

创建头文件Singleton.h存放头文件:

#define SingletonH(methodName) + (instancetype)shared##methodName;#define SingletonM(methodName) \
static id _instance = nil; \
+ (instancetype)allocWithZone:(struct _NSZone *)zone { \if (!_instance) { \static dispatch_once_t onceToken; \dispatch_once(&onceToken, ^{ \_instance = [super allocWithZone:zone]; \}); \} \return _instance; \
} \
\
- (instancetype)init { \static dispatch_once_t onceToken; \dispatch_once(&onceToken, ^{ \_instance = [super init]; \}); \return _instance; \
} \
\
+ (instancetype)shared##methodName { \return [[self alloc] init]; \
}

SingletonH(methodName)为声明宏,SingletonM(methodName)为实现宏。在每一行后面加上(反斜杠)取消换行,使用##来拼接传入的方法名,需要注意的是:最后一行不能加反斜杠。

SingletonClass.h文件中直接声明shareSingleMethod方法:

#import "Singleton.h"@interface SingletonClass : NSObject
SingletonH(SingleMethod);
@end

将方法名SingleMethod传入SingletonH();中就可以拼接为shareSingleMethod

SingletonClass.m直接实现创建单例类

#import "SingletonClass.h"@implementation SingletonClass
SingletonM(SingleMethod);
@end

运行结果:

请添加图片描述

最终我们仅仅用了“两”行代码,成功创建出了一个单例类,这样是不是节省了大量多余冗杂的代码呢。

Demo

【Github】使用单例进行传值

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/24365.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

使用Colaboratory免费GPU资源微调Llama3-8b

Llama3微调过程 准备工作 Google Colaboratory Google Colaboratory,也称为 Colab,是一个基于云的平台,允许用户编写和执行 Python 代码。 它为机器学习和数据分析任务提供了便利的环境,并内置了对 TensorFlow 等流行库的支持。…

1.vue2.x-初识及环境搭建

目录 1.下载nodejs v16.x 2.设置淘宝镜像源 3.安装脚手架 4.创建一个项目 5.项目修改 代码地址:source-code: 源码笔记 1.下载nodejs v16.x 下载地址:Node.js — Download Node.js 2.设置淘宝镜像源 npm config set registry https://registry.…

【c语言】指针就该这么学(3)

🌟🌟作者主页:ephemerals__ 🌟🌟所属专栏:C语言 目录 一、函数指针 1.函数指针变量的创建 2.函数指针变量的使用 二、typedef关键字 三、函数指针数组 1.函数指针数组的概念 2.函数指针数…

从零开始实现自己的串口调试助手(8)-循环发送

循环发送 准备 创建槽函数 设置QSpinBox的最大值 注意: // 我们不能在qt的ui线程中延时,否则将导致页面刷新问题 //QThread::msleep(ui->spinBox->text().toInt());//设置下次发送时间间隔 定时器实现 关联信号与槽: //添加自动换行定…

Pycharm创建Conda虚拟环境时显示CondaHTTPErOT

原因:conda源出问题了,之前可以用,现在报错。 最好的解决方案:找到conda源,换源即可。 步骤: 1.修改 .condarc 文件(文件的位置在:C:\Users\(你的用户名)\.condarc)&a…

Python中的@staticmethod和@classmethod装饰器

名词解释 本文主要介绍静态方法staticmethod和类方法classmethod在类中的应用,在介绍这两个函数装饰器之前,先介绍类中的几个名词,便于后面的理解: 类对象:定义的类就是类对象 类属性:定义在__init__ 外…

基于自动化工具autox.js的抢票(猫眼)

1.看到朋友圈抢周杰伦、林俊杰演唱会票贼难信息,特研究了一段时间,用autox.js写了自动化抢票脚本,购票页面自动点击下单(仅限安卓手机)。 2.脚本运行图 3.前期准备工作 (1)autox.js社区官网&am…

DNF手游攻略:主C职业推荐,云手机强力辅助!

在《地下城与勇士》手游中,你是否厌倦了重复刷图和无休止的手动操作?利用VMOS云手机,你可以一键解决这些烦恼,实现自动打怪、一机多开,让游戏变得更加轻松愉快。下面我们将介绍如何使用VMOS云手机,以及推荐…

MySQL-Explain使用

MySQL-Explain使用 type列 type列 这一列表示关联类型或访问类型,即MySQL决定如何查找表中的行,查找数据行记录的大概范围。 依次从最优到最差分别为:system > const > eq_ref > ref > range > index > ALL 一般来说&…

rk3568 norflash+pcei nvme 配置

文章目录 rk3568 norflashpcei nvme 配置1,添加parameter_nor.txt文件2 修改编译规则3 修改uboot4 修改BoardConfig.mk5 修改kernel pcei配置6 编译7 烧录 rk3568 norflashpcei nvme 配置 1,添加parameter_nor.txt文件 device/rockchip/rk356x/rk3568_…

【学习笔记】Windows GDI绘图(十三)动画播放ImageAnimator(可调速)

文章目录 前言定义方法CanAnimate 是否可动画显示Animate 动画显示多帧图像UpdateFramesStopAnimate终止动画Image.GetFrameCount 获取动画总帧数Image.GetPropertyItem(0x5100) 获取帧延迟 自定义GIF播放(可调速) 前言 在前一篇文章中用到ImageAnimator获取了GIF动画的一些属…

vue3 监听器,组合式API的watch用法

watch函数 在组合式 API 中,我们可以使用 watch 函数在每次响应式状态发生变化时触发回调函数 watch(ref,callback(newValue,oldValue),option:{}) ref:被监听的响应式量,可以是一个 ref (包括计算属性)、一个响应式…

STM32—按键控制LED(定时器)

目录 1 、 电路构成及原理图 2 、编写实现代码 main.c exit.c 3、代码讲解 4、烧录到开发板调试、验证代码 5、检验效果 此笔记基于朗峰 STM32F103 系列全集成开发板的记录。 1 、 电路构成及原理图 EXTI(External interrupt/event controller&#xff…

查询SQL02:寻找用户推荐人

问题描述 找出那些 没有被 id 2 的客户 推荐 的客户的姓名。 以 任意顺序 返回结果表。 结果格式如下所示。 题目分析: 这题主要是要看这null值会不会用,如果说Java玩多了,你去写SQL时就会有问题。在SQL中判断是不是null值用的是is null或…

泛微开发修炼之旅--10基于Ecology实现附件上传,并将上传后的文件id存入表单附件控件中的示例及源码

文章链接:泛微开发修炼之旅--10基于Ecology实现附件上传,并将上传后的文件id存入表单附件控件中的示例及源码

tomcat10部署踩坑记录-公网IP和服务器系统IP搞混

1. 服务器基本条件 使用的阿里云服务器,镜像系统是Ubuntu16.04java version “17.0.11” 2024-04-16 LTS装的是tomcat10.1.24阿里云服务器安全组放行了:8080端口 服务器防火墙关闭: 监听情况和下图一样: tomcat正常启动&#xff…

MySQL进阶——索引使用规则

在上篇文章我们学习了MySQL进阶——索引,这篇文章学习MySQL进阶——索引使用规则。 索引使用规则 在使用索引时,需要遵守一些使用规则,否则索引会部分失效或全部失效。 最左前缀法则 最左前缀法则是查询从索引的最左列开始,并…

Vxe UI vxe-form 实现折叠表单,当表单很多时实现自动收起与展开

Vxe UI vue vxe-form 实现折叠表单&#xff0c;当表单很多时实现自动收起与展开 代码 folding 用于将当前表单项设置为默认隐藏 collapse-node 设置折叠按钮&#xff0c;加上之后会自动在该表单项的右侧显示一个折叠按钮 <template><div><vxe-formtitle-colo…

谷歌上架防关联,打包环境到底是不是关联因素之一?

在Google play上架应用&#xff0c;防关联是开发者们最关注的问题之一&#xff0c;只要开发者账号被谷歌审核系统与其它违规的开发者账号或应用存在关联&#xff0c;就很有可能被封号。 如果账号被封了&#xff0c;通常谷歌的封号通知邮件里只是写了因为关联或高风险、多次违规…

kafka-生产者拦截器(SpringBoot整合Kafka)

文章目录 1、生产者拦截器1.1、创建生产者拦截器1.2、KafkaTemplate配置生产者拦截器1.3、使用Java代码创建主题分区副本1.4、application.yml配置----v1版1.5、屏蔽 kafka debug 日志 logback.xml1.6、引入spring-kafka依赖1.7、控制台日志 1、生产者拦截器 1.1、创建生产者拦…