AJ学IOS(52)多线程网络之GCD下单例设计模式
AJ分享,必须精品
单例模式
1:单例模式的作用
可以保证在程序运行过程,一个类只有一个实例,而且该实例易于供外界访问
从而方便地控制了实例个数,并节约系统资源
单例模式的使用场合
在整个应用程序中,共享一份资源(这份资源只需要创建初始化1次)
简单来说,就是我弄了一个工具类,他就有一份,比如我设计了一个音乐播放器NYPlayer,这个播放器类我就想他有一个,这就是单例,我用的时候我只需要让播放器干活,如果多个的话我不知道指定那个,或者有重复会出bug。
百度百科是这样说的:单例模式是一种常用的软件设计模式。在它的核心结构中只包含一个被称为单例类的特殊类。通过单例模式可以保证系统中一个类只有一个实例而且该实例易于外界访问,从而方便对实例个数的控制并节约系统资源。如果希望在系统中某个类的对象只能存在一个,单例模式是最好的解决方案。
简单来说,就是让一个类的事物里面只有一个对象。
2:ARC中,单例模式的实现
过程:
在.m中保留一个全局的static的实例
这里要用static,记住他,稍后我回写一个关于static关键词的博客。
static id _instance;
重写allocWithZone:方法,在这里创建唯一的实例(注意线程安全)
创建类的时候调用[类名 alloc]方法的时候,内部会自动调用allcWithZone方法,加载一个空间,所以我们只要重写这个方法,当我们定义的全局变量instance有值得时候,就会直接返回,如果没有,就会调用父类方法[super allocWithZone:zone]并赋值给instance,但是这时候有一个危险,那就是如果这里有两个线程都进来了,那样就会分配两次,所以我们要给本段程序加锁。
+ (id)allocWithZone:(struct _NSZone *)zone {
if (_instance == nil) { // 防止频繁加锁
@synchronized(self) {
if (_instance == nil) { // 防止创建多次
_instance = [super allocWithZone:zone];
}
}
}
return _instance;
}
提供一个类方法让外界访问唯一的实例。
跟上面的allocWithzone一样,不过有所不同的是这里调用的时【[self alloc] init】方法。
+ (instancetype)sharedMusicTool {
if (_instance == nil) { // 防止频繁加锁
@synchronized(self) {
if (_instance == nil) { // 防止创建多次
_instance = [[self alloc] init];
}
}
}
return _instance;
}
实现copyWithZone:方法
- (id)copyWithZone:(struct _NSZone *)zone {
return _instance;
}
3:MRC中的单例模式
过程:
非ARC中(MRC),单例模式的实现(比ARC多了几个步骤)
实现内存管理方法。
- (id)retain { return self; }//父类里面是计数器+1,重写将不会+1
- (NSUInteger)retainCount { return 1; }//父类里面返回当前对象的计数个数
- (oneway void)release {}//父类里面是计数器-1,重写将不会-1
- (id)autorelease { return self; }//父类里面内存自动管理释放的,跟内存池有关
GCD下完美单例模式(ARC&MRC通吃)
判断ARC的宏
这里首先要知道一个宏了 __has_feature(objc_arc)
单例模式在ARC\MRC环境下的写法有所不同,需要编写2套不同的代码
可以用宏判断是否为ARC环境。
#if __has_feature(objc_arc)
// ARC
#else
// MRC
#endif
传值的宏
就一句
#define NYSingletonH(name) + (instancetype)shared##name;
用的时候传进name,他就会自动替换了。
用GDC运行一次代码解决
怎么解决呢 ?其实就是把加锁换成GCD的一次性代码
代码如下:
+(id)allocWithZone:(struct _NSZone *)zone
{
if (_instance == nil) {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
if (_instance == nil) {
_instance = [super allocWithZone:zone];
}
});
}
return _instance;
}
快捷方式,xcode中只要敲dispatch_once就自动有啦,填填写写。
终极方式,以后单例不用敲代码了,直接掉就行了。
第一步,简历一个.h文件,例如
第二步,文件中写入以下代码:
// .h文件
#define NYSingletonH(name) + (instancetype)shared##name;
// .m文件
#define NYSingletonM
#if __has_feature(objc_arc)
#define NYSingletonM(name)\
static id _instance;\
\
+(id)allocWithZone:(struct _NSZone *)zone\
{\
if (_instance == nil) {\
static dispatch_once_t onceToken;\
dispatch_once(&onceToken, ^{\
if (_instance == nil) {\
_instance = [super allocWithZone:zone];\
}\
});\
}\
return _instance;\
}\
\
+(instancetype)shared##name\
{\
if (_instance == nil) {\
static dispatch_once_t onceToken;\
dispatch_once(&onceToken, ^{\
if (_instance == nil) {\
_instance = [[self alloc]init];\
}\
});\
}\
return _instance;\
}\
\
-(id)copyWithZone:(NSZone *)zone\
{\
return _instance;\\
}
#else
#define NYSingletonM(name)\
static id _instance;\
\
+(id)allocWithZone:(struct _NSZone *)zone\
{\
if (_instance == nil) {\
static dispatch_once_t onceToken;\
dispatch_once(&onceToken, ^{\
if (_instance == nil) {\
_instance = [super allocWithZone:zone];\
}\
});\
}\
return _instance;\
}\
\
+(instancetype)shared##name\
{\
if (_instance == nil) {\
static dispatch_once_t onceToken;\
dispatch_once(&onceToken, ^{\
if (_instance == nil) {\
_instance = [[self alloc]init];\
}\
});\
}\
return _instance;\
}\
\
-(id)copyWithZone:(NSZone *)zone\
{\
return _instance;\
}\
\
-(id)retain\
{\
return self;\
}\
-(NSUInteger)retainCount{return 1;}\
-(oneway void)release{}\
-(id)autorelease{return self;}
#endif
\符号是让后面的东东包含到上一行去,因为define只能定义一行。
第三步:在pch文件中写入调用代码:
#import "NYSingleton.h"
第四步:在需要用到的类中调用:
在点h文件中调用这个
在点m文件中调用这个
最后调用,还是单例:
补充,自定义宏代替NSLog
注意:开发过程中,会使用NSLog来打印信息用于调试,但releae的软件却不能包含NSLog,可能会有被打回的风险,但是要是全部注释掉NSLog那太痛苦了,也不利于以后的调试。
下面,我们可以采用自定义宏来取代NSLog,只在我们想要的时候输出
/*
XCode LLVM XXX - Preprocessing中Debug会添加 DEBUG=1 标志
*/
#ifdef DEBUG
#define NSLog(FORMAT, ...) fprintf(stderr,"%s:%d\t%s\n",[[[NSString stringWithUTF8String:__FILE__] lastPathComponent] UTF8String], __LINE__, [[NSString stringWithFormat:FORMAT, ##__VA_ARGS__] UTF8String]);
#else
#define NSLog(FORMAT, ...) nil
#endif
把以上代码粘贴到ProjectName-Prefix.pch文件中。
在调试的时候,会输出(格式:文件名:行号)日志。
在Release正式版本的时候,会关闭日志输出。
因为XCode LLVM XXX - Preprocessing中Debug会添加 DEBUG=1 标志。当然我们也能把DEBUG直接换成数字1来设置。
AJ学IOS(52)多线程网络之GCD下单例设计模式的更多相关文章
- AJ学IOS(48)多线程网络之多线程简单了解
AJ分享,必须精品 一:进程和线程 1:什么是进程 进程是指在系统中正在运行的一个应用程序 每个进程之间是独立的,每个进程均运行在其专用且受保护的内存空间内. 比如同时打开QQ.Xcode,系统就会分 ...
- iOS开发多线程篇 08 —GCD的常见用法
iOS开发多线程篇—GCD的常见用法 一.延迟执行 1.介绍 iOS常见的延时执行有2种方式 (1)调用NSObject的方法 [self performSelector:@selector(run) ...
- iOS开发多线程篇 07 —GCD的基本使用
iOS开发多线程篇—GCD的基本使用 一.主队列介绍 主队列:是和主线程相关联的队列,主队列是GCD自带的一种特殊的串行队列,放在主队列中得任务,都会放到主线程中执行. 提示:如果把任务放到主队列中进 ...
- iOS开发多线程篇 05 —GCD介绍
iOS开发多线程篇—GCD介绍 一.简单介绍 1.什么是GCD? 全称是Grand Central Dispatch,可译为“牛逼的中枢调度器” 纯C语言,提供了非常多强大的函数 2.GCD的优势 G ...
- AJ学IOS 之微博项目实战(2)微博主框架-自定义导航控制器NavigationController
AJ分享,必须精品 一:添加导航控制器 上一篇博客完成了对底部的TabBar的设置,这一章我们完成自定义导航控制器(NYNavigationController). 为啥要做自定义呢,因为为了更好地封 ...
- AJ学IOS(13)UI之UITableView学习(下)汽车名牌带右侧索引
AJ分享,必须精品 先看效果图 代码 ViewController #import "NYViewController.h" #import "NYCarGroup.h& ...
- AJ学IOS(50)多线程网络之GCD简单介绍(任务,队列)
AJ分享,必须精品 GCD简单介绍 1.什么是GCD? 全称是Grand Central Dispatch,可译为“牛逼的中枢调度器” 纯C语言,提供了非常多强大的函数 2.GCD的优势 GCD是苹果 ...
- AJ学IOS(51)多线程网络之GCD下载合并图片_队列组的使用
AJ分享,必须精品 合并图片(图片水印)第一种方法 效果 实现: 思路: 1.分别下载2张图片:大图片.LOGO 2.合并2张图片 3.显示到一个imageView身上 // 异步下载 dispatc ...
- AJ学IOS(49)多线程网络之线程的创建NSThreand
AJ分享,必须精品 一:NSThread的基本使用 1:创建和启动线程 一个NSThread对象就代表一条线程 创建.启动线程 NSThread *thread = [[NSThread alloc] ...
随机推荐
- Kubernetes实战总结 - 系统初始化
设置系统主机名以及Host文件的相互解析 hostnamectl set-hostname k8s-master01 cat >> /etc/hosts <<EOF 192.1 ...
- MySQL 【进阶查询】
数据类型介绍 整型 tinyint, # 占1字节,有符号:-128~127,无符号位:0~255 smallint, # 占2字节,有符号:-32768~32767,无符号位:0~65535 med ...
- 【短道速滑一】OpenCV中cvResize函数使用双线性插值缩小图像到长宽大小一半时速度飞快(比最近邻还快)之异象解析和自我实现。
今天,一个朋友想使用我的SSE优化Demo里的双线性插值算法,他已经在项目里使用了OpenCV,因此,我就建议他直接使用OpenCV,朋友的程序非常注意效率和实时性(因为是处理视频),因此希望我能测试 ...
- JDBC(四)----数据库连接池
## 数据库连接池 * 概念:其实就是一个容器(集合) * 当系统初始化好后,容器被创建,容器中会申请一些连接对象,当用户来访问数据库时,从容器中获取连接对象,用户访问完之后会将连接对象归还给容 ...
- ubuntu 16.04配置svn服务器
为了操作方便,使用root登录服务器. 一.安装svn服务器 -->apt-get install subversion 二.创建svn版本库,存放需要管理内容路径 -->mkdir sv ...
- 数据源管理 | 主从库动态路由,AOP模式读写分离
本文源码:GitHub·点这里 || GitEE·点这里 一.多数据源应用 1.基础描述 在相对复杂的应用服务中,配置多个数据源是常见现象,例如常见的:配置主从数据库用来写数据,再配置一个从库读数据, ...
- win 7 系统过期处理办法
超级尴尬,刚装的win7 系统居然过期了.下次再也不装盗版了,吼吼吼 处理方法就是下载oem7F7 软件安装,不用再怎么操作就好了. 就是这么简单,并不用像网上那样找什么激活码.
- 多GPU使用详解
目录: 介绍 记录设备状态 手动分配状态 允许GPU内存增长 在多GPU系统是使用单个GPU 使用多个 GPU 一.介绍 在一个典型的系统中,有多个计算设备.在 TensorFlow 中支持的设备类型 ...
- Github标星过万,Python新手100天学习计划,这次再学不会算我输!
作为目前最火也是最实用的编程语言,Python不仅是新手入门程序界的首选,也逐渐成为了从大厂到小厂,招牌需求list的必要一条. 当然,学Python这件事情,你可能也和文摘菌一样,已经下了一百次 ...
- linux-aapt文件调用问题
使用管理后台上传移动app安装包到服务器,出现异常问题,解决方案如下: 本地环境说明: 系统:linux(centos 64位) 远程工具:xshell 数据库:oracle 中间件:weblogic ...