GCD全解-dispatch_once-创建单例

简介: 单例是一种类,该类只在第一次用的时候实例化一个对象,后期直接调用此对象。在Foundation框架中比如NSFileManger和NSNotificationCenter,分别通过它们的类方法defaultManager和defaultCenter获取。尽管不是严格意义的单例,这些类方法返回一个可以在应用的所有代码中访问到的类的共享实例。

前言


单例是一种类,该类只在第一次用的时候实例化一个对象,后期直接调用此对象。

在Foundation框架中比如NSFileManger和NSNotificationCenter,分别通过它们的类方法defaultManager和defaultCenter获取。尽管不是严格意义的单例,这些类方法返回一个可以在应用的所有代码中访问到的类的共享实例。


2、原理


单例函数dispatch_once:


void dispatch_once( dispatch_once_t *predicate, dispatch_block_t block);

该函数接收一个dispatch_once用于检查该代码块是否已经被调度的谓词(是一个长整型,实际上作为BOOL使用)。

还接收一个希望在应用的生命周期内仅被调度一次的代码块,对于本例就用于shared实例的实例化。

dispatch_once不仅意味着代码仅会被运行一次,而且还是线程安全的,这就意味着你不需要使用诸如@synchronized之类的来防止使用多个线程或者队列时不同步的问题。

如果被多个线程调用,该函数会同步等等直至代码块完成。


3、实例


+ (AccountManager *)sharedManager {
  static AccountManager *sharedInstance = nil;
  static dispatch_once_t predicate;
  dispatch_once(&predicate, ^{
  sharedInstance = [[self alloc] init];
  });
  return sharedInstance;
}


这就意味着你任何时候访问共享实例,需要做的仅是:


AccountManager *accountManager = [AccountManager sharedManager];

就这些,你现在在应用中就有了一个共享的实例,该实例只会被创建一次。


4、总结

优点:

1 线程安全

2 很好满足静态分析器要求

3 和自动引用计数(ARC)兼容

4 仅需要少量代码


缺点:

它仍然需要运行创建一个非共享的实例:


AccountManager *accountManager = [[AccountManager alloc] init];

有些时候你希望有这种行为,但如果正在想要的是仅一个实例被实例化就需要注意这点。


5、宏定义单例

//宏定义单例
// .h
#define SingletonH(class) + (instancetype)shared##class;
// .m
#define SingletonM(class) \
static class *_instance; \
\
+ (id)allocWithZone:(struct _NSZone *)zone \
{ \
static dispatch_once_t onceToken; \
dispatch_once(&onceToken, ^{ \
_instance = [super allocWithZone:zone]; \
}); \
\
return _instance; \
} \
\
+ (instancetype)shared##class \
{ \
if (_instance == nil) { \
_instance = [[class alloc] init]; \
} \
\
return _instance; \
}\
- (id)copyWithZone:(NSZone *)zone \
{ \
return _instance; \
}
相关文章
|
iOS开发 开发者
【教程】苹果 iOS 证书制作教程
【教程】苹果 iOS 证书制作教程
|
数据安全/隐私保护 iOS开发 开发者
iOS 逆向编程(十八)Reveal 详细安装(以及安装问题解决)(上)
iOS 逆向编程(十八)Reveal 详细安装(以及安装问题解决)
982 0
|
数据库 Android开发 开发者
Android Studio入门之内容共享ContentProvider讲解以及实现共享数据实战(附源码 超详细必看)
Android Studio入门之内容共享ContentProvider讲解以及实现共享数据实战(附源码 超详细必看)
599 0
|
存储 应用服务中间件 测试技术
Elasticsearch Data Stream 数据流使用
Elasticsearch Data Stream 数据流使用
364 0
|
人工智能 安全 数据挖掘
Pandas AI:Pandas与人工智能的结合,让你不再拘泥于如何使用pandas方法及处理语法
Pandas AI:Pandas与人工智能的结合,让你不再拘泥于如何使用pandas方法及处理语法
1694 1
|
虚拟化 KVM Linux
带你读《KVM实战:原理、进阶与性能调优》之二:KVM原理简介
本书兼具实战性、系统性又不乏深度的KVM虚拟化技术指南,既能让新人快速掌握KVM的基础知识,又能满足有经验的读者进阶学习的需求。本书两位作者来自于阿里云和Intel,在云计算和KVM方面有深入的研究,他们将自己的经验倾囊相授,带你全面了解KVM的各种技术细节。
|
存储 并行计算 算法
C++动态规划的全面解析:从原理到实践
C++动态规划的全面解析:从原理到实践
437 0
关于如何解决mingw64安装后配置完环境变量仍然执行不了gcc命令
关于如何解决mingw64安装后配置完环境变量仍然执行不了gcc命令
|
安全 编译器 API
程序与技术分享:C#调用DLL的几种方法
程序与技术分享:C#调用DLL的几种方法
1157 0
下一篇
oss云网关配置