【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

运行结果:

请添加图片描述

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

Demo

【Github】使用单例进行传值

在这里插入图片描述

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

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

相关文章

SpringBoot2+Vue3开发课程审核流程系统

SpringBoot2Vue3开发课程审核流程系统 简介 此系统实现了课程审核全流程功能并使用了Activiti7工作流技术,功能包含:课程管理、用户管理、流程定义、课程审核(我的申请、我的代办、我的已办) 功能介绍 课程管理 对课程信息的管…

C++的STL 中 set.map multiset.multimap 学习使用详细讲解(含配套OJ题练习使用详细解答)

目录 一、set 1.set的介绍 2.set的使用 2.1 set的模板参数列表 2.2 set的构造 2.3 set的迭代器 2.4 set的容量 2.5 set的修改操作 2.6 set的使用举例 二、map 1.map的介绍 2.map的使用 2.1 map的模板参数说明 2.2 map的构造 2.3 map的迭代器 2.4 map的容量与元…

API测试工具

apifox 微信扫描登录 不推荐: Download Postman

QT creator c动态链接库的创建与调用

QT creator c动态链接库的创建与调用 QT5.15.2 1.创建dll项目 确保两类型选择正确 2.选择MinGW 64-bit 3.点击完成 pro文件参考: QT - guiTEMPLATE lib DEFINES QT_DLL_DEMO_LIBRARYCONFIG c17# You can make your code fail to compile if it uses deprecat…

Flutter 使用ffigen生成ffmpeg的dart接口

Flutter视频渲染系列 第一章 Android使用Texture渲染视频 第二章 Windows使用Texture渲染视频 第三章 Linux使用Texture渲染视频 第四章 全平台FFICustomPainter渲染视频 第五章 Windows使用Native窗口渲染视频 第六章 桌面端使用texture_rgba_renderer渲染视频 第七章 使用ff…

以sqlilabs靶场为例,讲解SQL注入攻击原理【54-65关】

【Less-54】 与前面的题目不同是,这里只能提交10次,一旦提交超过十次,数据会重新刷新,所有的步骤需要重来一次。 解题步骤: 根据测试,使用的是单引号闭合。 # 判断字段的数量 ?id1 order by 3 -- aaa# …

.NET MAUI 了解MVVM

MVVM 模式中有三个核心组件:模型、视图和视图模型。 每个组件的用途不同。 下图显示了这三个组件之间的关系。 视图 视图负责定义用户在屏幕上看到的结构、布局和外观。 理想情况下,每个视图在 XAML 中定义,代码隐藏有限,不包含业…

(论文翻译)Coordinate Attention for Efficient Mobile Network Design(坐标注意力 CVPR2021)

Coordinate Attention for Efficient Mobile Network Design(CVPR2021) 文章目录 Coordinate Attention for Efficient Mobile Network Design(CVPR2021)摘要1.引言2.相关工作3.方法:Coordinate Attention3.1.Revisit …

RHEL8/Centos8 install for PXE

PXE介绍 PXE(Preboot Execution Environment)是预引导执行环境的缩写。它是由Intel设计的,允许客户端计算机通过网络从服务器上加载操作系统镜像。PXE通常用于大规模部署操作系统,例如在企业或学校环境中。 PXE工作流程如下&…

C++ | Leetcode C++题解之第139题单词拆分

题目&#xff1a; 题解&#xff1a; class Solution { public:bool wordBreak(string s, vector<string>& wordDict) {auto wordDictSet unordered_set <string> ();for (auto word: wordDict) {wordDictSet.insert(word);}auto dp vector <bool> (s.…

【el-tooltips改造】Vue实现文本溢出才显示el-tooltip,否则不显示el-tooltips

实现原理&#xff1a; 使用disabled属性控制el-tooltip的content显示与隐藏&#xff1b; 目标&#xff1a; 1行省略、多行省略、可缩放页面内的文本省略都有效。 实现方式&#xff1a; 1、自定义全局指令&#xff0c;tooltipAutoShow.js代码如下&#xff08;参考的el-table中的…

04 架构核心技术之分布式消息队列

本课时的主题是分布式消息队列&#xff0c;分布式消息队列的知识结构如下图。 本课时主要介绍以下内容。 同步架构和异步架构的区别。异步架构的主要组成部分&#xff1a;消息生产者、消息消费者、分布式消息队列。异步架构的两种主要模型&#xff1a;点对点模型和发布订阅模型…

C# 异步方法async / await 任务超时处理

一、需求 如果调用一个异步方法后&#xff0c;一直不给返回值结果怎么办呢&#xff1f;这就涉及到怎么取消任务了。 二、Task取消任务 static CancellationTokenSource source new CancellationTokenSource();static void Main(string[] args){Task.Run(() >{for (int i …

【基于C++与OpenCV实现魔方图像识别和还原算法】施工总览图

文章目录 主要效果展示思维导图魔方还原算法 本系列博客长期更新&#xff0c;分为两大部分 OpenCV实现魔方六面识别 C编写科先巴二阶段还原算法实现三阶魔方的还原 主要效果展示 摄像头识别六面 3D图像构建&#xff0c;提供还原公式 动画演示还原过程 思维导图 魔方还原算法 参…

PowerDesigner导入Excel模板生成数据表

PowerDesigner导入Excel模板生成数据表 1.准备好需要导入的Excel表结构数据,模板内容如下图所示 2.打开PowerDesigner,新建一个physical data model文件,填入文件名称,选择数据库类型 3.点击Tools|Execute Commands|Edit/Run Script菜单或按下快捷键Ctrl Shift X打开脚本窗口…

免费开源图片转文字识别软件:Umi-OCR

目录 1.介绍 2.项目亮点 3.项目功能&#xff08;已实现&#xff09; 4.功能体验 5.项目集成&#xff08;调用接口&#xff09; 6.项目地址 1.介绍 Umi-OCR&#xff1a;免费&#xff0c;开源&#xff0c;可批量的离线OCR软件&#xff0c;目前适用于 Windows7 x64 及以上。…

【机器人和人工智能——自主巡航赛项】进阶篇

文章目录 案例要求创建地图rviz仿真 保存地图坐标点定位识别训练主逻辑理解语音播报模块匹配二维码识别多点导航讲解视频其余篇章 案例要求 创建地图 ./1-gmapping.sh 把多个launch文件融合在sh文件里面 rviz仿真 rviz是rose集成的可视化界面&#xff0c;查看机器人的各项数…

深度学习:如何静悄悄地改变我们的日常生活

深度学习 深度学习&#xff1a;如何静悄悄地改变我们的日常生活一、消费电子产品智能手机与个人助理娱乐与社交媒体 二、医疗健康三、汽车与交通四、公共安全五、总结 深度学习&#xff1a;如何静悄悄地改变我们的日常生活 在近年来&#xff0c;深度学习技术因其强大的数据处理…

Java——数组排序和查找

一、排序介绍 1、排序的概念 排序是将多个数据按照指定的顺序进行排列的过程。 2、排序的种类 排序可以分为两大类&#xff1a;内部排序和外部排序。 3、内部排序和外部排序 1&#xff09;内部排序 内部排序是指数据在内存中进行排序&#xff0c;适用于数据量较小的情况…

快速入门Linux及使用VSCode远程连接Linux服务器

在当前的技术环境中&#xff0c;Linux操作系统因其强大的功能和灵活性而广受欢迎。无论你是开发人员、系统管理员还是技术爱好者&#xff0c;学习Linux都是提升技术技能的重要一步。本文将介绍如何快速入门Linux&#xff0c;并使用Visual Studio Code&#xff08;VSCode&#x…