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; \
}
相关文章
|
3月前
|
API 调度 iOS开发
多线程和异步编程:什么是 GCD(Grand Central Dispatch)?如何在 iOS 中使用 GCD?
多线程和异步编程:什么是 GCD(Grand Central Dispatch)?如何在 iOS 中使用 GCD?
28 1
|
iOS开发
iOS多线程的初步研究-- dispatch同步
GCD提供两种方式支持dispatch队列同步,即dispatch组和信号量。
147 0
|
前端开发 Java 开发者
Dispatch 设计| 学习笔记
快速学习 Dispatch 设计。
Dispatch 设计| 学习笔记
|
Java Spring
05DispatcherServlet的初始化策略
流程回顾及后续规划 接收到spring之后回调之后的初始化策略
112 0
|
安全 iOS开发
GCD全解-dispatch-多个网络请求处理
在开发中,我们会经常遇到这样的需求,需要我们同时做多个网络请求,然后架构所需数据,再统一渲染页面。
190 0
GCD全解-dispatch_queue-队列创建
GCD全解-dispatch_queue-队列创建
257 0
GCD全解-dispatch_after/dispatch_time-t延迟操作
GCD全解-dispatch_after/dispatch_time-t延迟操作
259 0
GCD全解-dispatch_barrier_sync/async-栅栏函数
GCD全解-dispatch_barrier_sync/async-栅栏函数
242 0
|
前端开发 Java 开发者
Dispatch设计|学习笔记
快速学习Dispatch设计
Dispatch设计|学习笔记
|
JavaScript 中间件
Fish Redux中的Dispatch是怎么实现的?
作者:闲鱼技术-卢克 零.前言 我们在使用fish-redux构建应用的时候,界面代码(view)和事件的处理逻辑(reducer,effect)是完全解耦的,界面需要处理事件的时候将action分发给对应的事件处理逻辑去进行处理,而这个分发的过程就是下面要讲的dispatch, 通过本篇的内容,你可以更深刻的理解一个action是如何一步步去进行分发的。
2627 0