赞
踩
1)全称是Grand Central Dispatch,可译为“牛逼的中枢调度器”
2)纯C语言,提供了非常多强大的函数
1)GCD是苹果为多核的并行运算提出的解决方案。
2)GCD会自动利用更多的CPU内核(比如双核,四核)。
3)GCD会自动管理线程的生命周期(创建线程,调度任务)。
1)任务:执行什么操作
2)队列:用来存放任务
1)定制任务(确定想做的事)
2)将任务添加到队列(GCD会自动将队列中的任务取出,放到对应的线程中去执行; 任务的取出遵循队列的FIFO原则:先进先出,后进后出(栈是先进后出))
GCD中有2个用来执行任务的常用函数
1) 用同步的方式执行任务
dispatch_sync(dispatch_queue_t queue, dispatch_block_t block): queue: 队列 block: 任务
2)用异步的方式执行任务
dispatch_async(dispatch_queue_t queue, dispatch_block_t block)
1)同步:只能在当前的线程中执行任务,不具备开启新线程的能力
2)异步:可以在新的线程中执行任务,具备开启新线程的能力
GCD的队列可以分为两大类型
1. 并发队列
1) 可以让多个任务并发同时执行(自动开启多个线程自动执行任务)
2)并发功能只有在异步(dispatch_async)函数下才有效
2. 串行队列
1)让任务一个接一个的执行(一个任务执行完毕后,再执行下一个任务)
有四个术语比较容易混淆:同步,异步,并发,串行
1. 同步和异步的主要区别:能不能开启新的线程
1)同步:只是在当前线程中执行任务,不具备开启新线程的能力
2)异步:可以在新的线程中执行,具备开启新线程的能力
2. 并发和串行的主要区别:任务的执行方式
1)并发:允许多个任务并发(同时)执行
2)串行:一个任务执行完毕后,再执行下一个任务
- #import "ViewController.h"
-
- @interface ViewController ()
-
- @end
-
- @implementation ViewController
-
- #pragma mark ----------------------
- #pragma Events
- -(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
- {
- // [NSThread detachNewThreadSelector:@selector(syncMain) toTarget:self withObject:nil];
-
- [self asyncConcurrent];
- }
-
- #pragma mark ----------------------
- #pragma Methods
- //异步函数+并发队列:会开启多条线程,队列中的任务是并发执行
- //注意:并不是有多少个任务就开启多少个线程,是由系统内部决定的
- -(void)asyncConcurrent
- {
- //1.创建队列
- /*
- 第一个参数:C语言的字符串,标签
- 第二个参数:队列的类型
- DISPATCH_QUEUE_CONCURRENT:并发
- DISPATCH_QUEUE_SERIAL:串行
- */
- //dispatch_queue_t queue = dispatch_queue_create("com.www.download", DISPATCH_QUEUE_CONCURRENT);
-
- //获得全局并发队列
- /*
- 第一个参数:优先级
- 第二个参数:
- */
- dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
-
- NSLog(@"---satrt----");
-
- //2.1>封装任务2>添加任务到队列中
- /*
- 第一个参数:队列
- 第二个参数:要执行的任务
- */
- dispatch_async(queue, ^{
- NSLog(@"download1----%@",[NSThread currentThread]);
- });
-
- dispatch_async(queue, ^{
- NSLog(@"download2----%@",[NSThread currentThread]);
- });
-
- dispatch_async(queue, ^{
- NSLog(@"download3----%@",[NSThread currentThread]);
- });
-
- NSLog(@"---end----");
- }
-
- //异步函数+串行队列:会开线程,开一条线程,队列中的任务是串行执行的
- -(void)asyncSerial
- {
- //1.创建队列
- dispatch_queue_t queue = dispatch_queue_create("download", DISPATCH_QUEUE_SERIAL);
-
- //2.封装操作
- dispatch_async(queue, ^{
- NSLog(@"download1----%@",[NSThread currentThread]);
- });
-
- dispatch_async(queue, ^{
- NSLog(@"download2----%@",[NSThread currentThread]);
- });
-
- dispatch_async(queue, ^{
- NSLog(@"download3----%@",[NSThread currentThread]);
- });
- }
-
- //同步函数+并发队列:不会开线程,任务是串行执行的
- -(void)syncConcurrent
- {
- //1.创建队列
- dispatch_queue_t queue = dispatch_queue_create("com.www.download", DISPATCH_QUEUE_CONCURRENT);
-
- NSLog(@"---start---");
- //2.封装任务
- dispatch_sync(queue, ^{
- NSLog(@"download1----%@",[NSThread currentThread]);
- });
-
- dispatch_sync(queue, ^{
- NSLog(@"download2----%@",[NSThread currentThread]);
- });
-
- dispatch_sync(queue, ^{
- NSLog(@"download3----%@",[NSThread currentThread]);
- });
-
- NSLog(@"---end---");
- }
-
- //同步函数+串行队列:不会开线程,任务是串行执行的
- -(void)syncSerial
- {
- //1.创建队列
- dispatch_queue_t queue = dispatch_queue_create("com.www.download", DISPATCH_QUEUE_SERIAL);
-
- //2.封装任务
- dispatch_sync(queue, ^{
- NSLog(@"download1----%@",[NSThread currentThread]);
- });
-
- dispatch_sync(queue, ^{
- NSLog(@"download2----%@",[NSThread currentThread]);
- });
-
- dispatch_sync(queue, ^{
- NSLog(@"download3----%@",[NSThread currentThread]);
- });
- }
-
- //异步函数+主队列:所有任务都在主线程中执行,不会开线程
- -(void)asyncMain
- {
- //1.获得主队列
- dispatch_queue_t queue = dispatch_get_main_queue();
-
- //2.异步函数
- dispatch_async(queue, ^{
- NSLog(@"download1----%@",[NSThread currentThread]);
- });
-
- dispatch_async(queue, ^{
- NSLog(@"download2----%@",[NSThread currentThread]);
- });
-
- dispatch_async(queue, ^{
- NSLog(@"download3----%@",[NSThread currentThread]);
- });
- }
-
- //同步函数+主队列:死锁
- //注意:如果该方法在子线程中执行,那么所有的任务在主线程中执行,不会死锁
- -(void)syncMain
- {
- //1.获得主队列
- dispatch_queue_t queue = dispatch_get_main_queue();
-
- NSLog(@"start----");
- //2.同步函数
- //同步函数:立刻马上执行,如果我没有执行完毕,那么后面的也别想执行
- //异步函数:如果我没有执行完毕,那么后面的也可以执行
- dispatch_sync(queue, ^{
- NSLog(@"download1----%@",[NSThread currentThread]);
- });
-
- dispatch_sync(queue, ^{
- NSLog(@"download2----%@",[NSThread currentThread]);
- });
-
- dispatch_sync(queue, ^{
- NSLog(@"download3----%@",[NSThread currentThread]);
- });
-
- NSLog(@"end---");
- }
- @end
注意:使用sync(同步)函数往当前串行队列中添加任务,会卡住当前的串行队列,造成死锁
dispatch_async(
dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
// 执行耗时的异步操作...
dispatch_async(dispatch_get_main_queue(), ^{
// 回到主线程,执行UI刷新操作
});
});
- #import "ViewController.h"
-
- @interface ViewController ()
- @property (weak, nonatomic) IBOutlet UIImageView *imageView;
-
- @end
-
- @implementation ViewController
-
- -(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
- {
- //1.创建子线程下载图片
- //DISPATCH_QUEUE_PRIORITY_DEFAULT 0
- dispatch_async(dispatch_get_global_queue(0, 0), ^{
-
- //1.1 确定url
- NSURL *url = [NSURL URLWithString:@"http://a.hiphotos.baidu.com/zhidao/wh%3D450%2C600/sign=da0ec79c738da9774e7a8e2f8561d42f/c83d70cf3bc79f3d6842e09fbaa1cd11738b29f9.jpg"];
-
- //1.2 下载二进制数据到本地
- NSData *imageData = [NSData dataWithContentsOfURL:url];
-
- //1.3 转换图片
- UIImage *image = [UIImage imageWithData:imageData];
-
- NSLog(@"download----%@",[NSThread currentThread]);
-
- //更新UI
- // dispatch_async(dispatch_get_main_queue(), ^{
- dispatch_sync(dispatch_get_main_queue(), ^{
- self.imageView.image = image;
- NSLog(@"UI----%@",[NSThread currentThread]);
- });
-
- });
- }
-
- @end
1)调用NSObject的方法
[self performSelector:@selector(run) withObject:nil afterDelay:2.0];
// 2秒后再调run方法
2)使用GCD函数
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
// 2秒后执行这里的代码...
});
3)使用NSTimer
[NSTimer scheduledTimerWithTimeInterval:2.0 target:self selector:@selector(test) userInfo:nil repeats:NO];
4)一次性代码
- //使用dispatch_once函数能保证某段代码在程序运行过程中只被执行1次
- static dispatch_once_t onceToken;
- dispatch_once(&onceToken, ^{
- // 只执行1次的代码(这里面默认是线程安全的)
- });
5)代码示例
- #import "ViewController.h"
-
- @interface ViewController ()
-
- @end
-
- @implementation ViewController
-
- -(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
- {
- [self once];
- }
-
- //延迟执行
- -(void)delay
- {
- NSLog(@"start-----");
-
- //1. 延迟执行的第一种方法
- //[self performSelector:@selector(task) withObject:nil afterDelay:2.0];
-
- //2.延迟执行的第二种方法
- //[NSTimer scheduledTimerWithTimeInterval:2.0 target:self selector:@selector(task) userInfo:nil repeats:YES];
-
- //3.GCD
- // dispatch_queue_t queue = dispatch_get_main_queue();
- dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
- /*
- 第一个参数:DISPATCH_TIME_NOW 从现在开始计算时间
- 第二个参数:延迟的时间 2.0 GCD时间单位:纳秒
- 第三个参数:队列
- */
- dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0 * NSEC_PER_SEC)), queue, ^{
- NSLog(@"GCD----%@",[NSThread currentThread]);
- });
-
- }
-
- //一次性代码
- //不能放在懒加载中的,应用场景:单例模式
- -(void)once
- {
- static dispatch_once_t onceToken;
- dispatch_once(&onceToken, ^{
- NSLog(@"---once----");
- });
- }
-
- -(void)task
- {
- NSLog(@"task----%@",[NSThread currentThread]);
- }
- @end
dispatch_barrier_async(dispatch_queue_t queue, dispatch_block_t block);
在前面的任务执行结束后它才执行,而且它后面的任务等它执行完成之后才会执行
- #import "ViewController.h"
-
- @interface ViewController ()
-
- @end
-
- @implementation ViewController
-
- -(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
- {
-
- //0.获得全局并发队列
- //栅栏函数不能使用全局并发队列,只能使用自己创建的并发队列
- //dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
- dispatch_queue_t queue = dispatch_queue_create("download", DISPATCH_QUEUE_CONCURRENT);
-
- //1.异步函数
- dispatch_async(queue, ^{
-
- for (NSInteger i = 0; i<100; i++) {
- NSLog(@"download1-%zd-%@",i,[NSThread currentThread]);
- }
-
- });
-
- dispatch_async(queue, ^{
-
- for (NSInteger i = 0; i<100; i++) {
- NSLog(@"download2-%zd-%@",i,[NSThread currentThread]);
- }
- });
-
-
- //栅栏函数
- dispatch_barrier_async(queue, ^{
-
- NSLog(@"+++++++++++++++++++++++++++++");
- });
-
- dispatch_async(queue, ^{
-
- for (NSInteger i = 0; i<100; i++) {
- NSLog(@"download3-%zd-%@",i,[NSThread currentThread]);
- }
- });
-
- dispatch_async(queue, ^{
-
- for (NSInteger i = 0; i<100; i++) {
- NSLog(@"download4-%zd-%@",i,[NSThread currentThread]);
- }
- });
- }
-
- @end
- dispatch_apply(10, dispatch_get_global_queue(0, 0), ^(size_t index){
-
- // 执行10次代码,index顺序不确定
-
- });
剪切文件代码示例:
- #import "ViewController.h"
-
- @interface ViewController ()
-
- @end
-
- @implementation ViewController
-
- -(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
- {
- [self moveFileWithGCD];
- }
-
- -(void)forDemo
- {
- //同步,在主线程串行
- for (NSInteger i = 0; i<10; i++) {
- NSLog(@"%zd---%@",i,[NSThread currentThread]);
- }
- }
-
- //开子线程和主线程一起完成遍历任务,任务的执行时并发的
- -(void)applyDemo
- {
- /*
- 第一个参数:遍历的次数
- 第二个参数:队列(并发队列)
- 第三个参数:index 索引
- */
- dispatch_apply(10, dispatch_get_global_queue(0, 0), ^(size_t index) {
- NSLog(@"%zd---%@",index,[NSThread currentThread]);
- });
- }
-
- //使用for循环
- -(void)moveFile
- {
- //1.拿到文件路径
- NSString *from = @"/Users/Alan/Desktop/from";
-
- //2.获得目标文件路径
- NSString *to = @"/Users/Alan/Desktop/to";
-
- //3.得到目录下面的所有文件
- NSArray *subPaths = [[NSFileManager defaultManager] subpathsAtPath:from];
-
- NSLog(@"%@",subPaths);
- //4.遍历所有文件,然后执行剪切操作
- NSInteger count = subPaths.count;
-
- for (NSInteger i = 0; i< count; i++) {
-
- //4.1 拼接文件的全路径
- // NSString *fullPath = [from stringByAppendingString:subPaths[i]];
- //在拼接的时候会自动添加/
- NSString *fullPath = [from stringByAppendingPathComponent:subPaths[i]];
- NSString *toFullPath = [to stringByAppendingPathComponent:subPaths[i]];
-
- NSLog(@"%@",fullPath);
- //4.2 执行剪切操作
- /*
- 第一个参数:要剪切的文件在哪里
- 第二个参数:文件应该被存到哪个位置
- */
- [[NSFileManager defaultManager]moveItemAtPath:fullPath toPath:toFullPath error:nil];
-
- NSLog(@"%@---%@--%@",fullPath,toFullPath,[NSThread currentThread]);
- }
- }
-
- -(void)moveFileWithGCD
- {
- //1.拿到文件路径
- NSString *from = @"/Users/Alan/Desktop/from";
-
- //2.获得目标文件路径
- NSString *to = @"/Users/Alan/Desktop/to";
-
- //3.得到目录下面的所有文件
- NSArray *subPaths = [[NSFileManager defaultManager] subpathsAtPath:from];
-
- NSLog(@"%@",subPaths);
- //4.遍历所有文件,然后执行剪切操作
- NSInteger count = subPaths.count;
-
- dispatch_apply(count, dispatch_get_global_queue(0, 0), ^(size_t i) {
- //4.1 拼接文件的全路径
- // NSString *fullPath = [from stringByAppendingString:subPaths[i]];
- //在拼接的时候会自动添加/
- NSString *fullPath = [from stringByAppendingPathComponent:subPaths[i]];
- NSString *toFullPath = [to stringByAppendingPathComponent:subPaths[i]];
-
- NSLog(@"%@",fullPath);
- //4.2 执行剪切操作
- /*
- 第一个参数:要剪切的文件在哪里
- 第二个参数:文件应该被存到哪个位置
- */
- [[NSFileManager defaultManager]moveItemAtPath:fullPath toPath:toFullPath error:nil];
-
- NSLog(@"%@---%@--%@",fullPath,toFullPath,[NSThread currentThread]);
-
- });
- }
- @end
1)分别异步执行多个耗时的操作
2)等多个异步操作都执行完毕后,再回到主线程执行操作
3)拦截通知,当队列组中所有的任务都执行完毕的时候回进入到下面的方法,异步的,不会阻塞线程
- dispatch_group_t group = dispatch_group_create();
-
- dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
-
- // 执行1个耗时的异步操作
-
- });
-
- dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
-
- // 执行1个耗时的异步操作
-
- });
-
- dispatch_group_notify(group, dispatch_get_main_queue(), ^{
-
- // 等前面的异步操作都执行完毕后,回到主线程...
-
- });
下载两张图片合并成一张代码示例:
- #import "ViewController.h"
-
- @interface ViewController ()
- /** 图片1 */
- @property (nonatomic, strong) UIImage *image1;
- /** 图2 */
- @property (nonatomic, strong) UIImage *image2;
-
- @property (weak, nonatomic) IBOutlet UIImageView *imageView;
- @end
-
- @implementation ViewController
-
- #pragma mark ----------------------
- #pragma mark Events
-
- -(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
- {
- [self test];
- }
- #pragma mark ----------------------
- #pragma mark Methods
- -(void)group1
- {
- //1.创建队列
- dispatch_queue_t queue =dispatch_get_global_queue(0, 0);
-
- //2.创建队列组
- dispatch_group_t group = dispatch_group_create();
-
- //3.异步函数
- /*
- 1)封装任务
- 2)把任务添加到队列中
- dispatch_async(queue, ^{
- NSLog(@"1----%@",[NSThread currentThread]);
- });
- */
- /*
- 1)封装任务
- 2)把任务添加到队列中
- 3)会监听任务的执行情况,通知group
- */
- dispatch_group_async(group, queue, ^{
- NSLog(@"1----%@",[NSThread currentThread]);
- });
-
-
- dispatch_group_async(group, queue, ^{
- NSLog(@"2----%@",[NSThread currentThread]);
- });
-
- dispatch_group_async(group, queue, ^{
- NSLog(@"3----%@",[NSThread currentThread]);
- });
-
- //拦截通知,当队列组中所有的任务都执行完毕的时候回进入到下面的方法,异步的,不会阻塞线程
- dispatch_group_notify(group, queue, ^{
-
- NSLog(@"-------dispatch_group_notify-------");
- });
-
- NSLog(@"----end----");
-
- }
-
- -(void)group2
- {
- //1.创建队列
- dispatch_queue_t queue =dispatch_get_global_queue(0, 0);
-
- //2.创建队列组
- dispatch_group_t group = dispatch_group_create();
-
- //3.在该方法后面的异步任务会被纳入到队列组的监听范围,进入群组
- //dispatch_group_enter|dispatch_group_leave 必须要配对使用
- dispatch_group_enter(group);
-
- dispatch_async(queue, ^{
- NSLog(@"1----%@",[NSThread currentThread]);
-
- //离开群组
- dispatch_group_leave(group);
- });
-
- dispatch_group_enter(group);
-
- dispatch_async(queue, ^{
- NSLog(@"2----%@",[NSThread currentThread]);
-
- //离开群组
- dispatch_group_leave(group);
- });
-
-
- //拦截通知
- //问题?该方法是阻塞的吗? 内部本身是异步的
- // dispatch_group_notify(group, queue, ^{
- // NSLog(@"-------dispatch_group_notify-------");
- // });
-
- //等待.死等. 直到队列组中所有的任务都执行完毕之后才能执行
- //阻塞的,会阻塞线程
- dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
- NSLog(@"----end----");
-
- }
-
- -(void)group3
- {
- /*
- 1.下载图片1 开子线程
- 2.下载图片2 开子线程
- 3.合成图片并显示图片 开子线程
- */
-
- //-1.获得队列组
- dispatch_group_t group = dispatch_group_create();
-
- //0.获得并发队列
- dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
-
- // 1.下载图片1 开子线程
- dispatch_group_async(group, queue,^{
-
- NSLog(@"download1---%@",[NSThread currentThread]);
- //1.1 确定url
- NSURL *url = [NSURL URLWithString:@"http://www.qbaobei.com/tuku/images/13.jpg"];
-
- //1.2 下载二进制数据
- NSData *imageData = [NSData dataWithContentsOfURL:url];
-
- //1.3 转换图片
- self.image1 = [UIImage imageWithData:imageData];
- });
-
- // 2.下载图片2 开子线程
- dispatch_group_async(group, queue,^{
-
- NSLog(@"download2---%@",[NSThread currentThread]);
- //2.1 确定url
- NSURL *url = [NSURL URLWithString:@"http://pic1a.nipic.com/2008-09-19/2008919134941443_2.jpg"];
-
- //2.2 下载二进制数据
- NSData *imageData = [NSData dataWithContentsOfURL:url];
-
- //2.3 转换图片
- self.image2 = [UIImage imageWithData:imageData];
- });
-
- //3.合并图片
- //主线程中执行
- dispatch_group_notify(group, dispatch_get_main_queue(), ^{
-
- NSLog(@"combie---%@",[NSThread currentThread]);
- //3.1 创建图形上下文
- UIGraphicsBeginImageContext(CGSizeMake(200, 200));
-
- //3.2 画图1
- [self.image1 drawInRect:CGRectMake(0, 0, 200, 100)];
- self.image1 = nil;
-
- //3.3 画图2
- [self.image2 drawInRect:CGRectMake(0, 100, 200, 100)];
- self.image2 = nil;
-
- //3.4 根据上下文得到一张图片
- UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
-
- //3.5 关闭上下文
- UIGraphicsEndImageContext();
-
- //3.6 更新UI
- // dispatch_async(dispatch_get_main_queue(), ^{
-
- NSLog(@"UI----%@",[NSThread currentThread]);
- self.imageView.image = image;
- // });
- });
-
- // dispatch_release(group)
- }
-
- -(void)test
- {
- // dispatch_async(<#dispatch_queue_t queue#>, <#^(void)block#>)
- //区别:封装任务的方法(block--函数)
- /*
- 第一个参数:队列
- 第二个参数:参数
- 第三个参数:要调用的函数的名称
- */
- dispatch_async_f(dispatch_get_global_queue(0, 0), NULL, task);
- dispatch_async_f(dispatch_get_global_queue(0, 0), NULL, task);
- dispatch_async_f(dispatch_get_global_queue(0, 0), NULL, task);
- }
-
- void task(void *param)
- {
- NSLog(@"%s---%@",__func__,[NSThread currentThread]);
- }
-
- @end
1)可以保证在程序运行过程,一个类只有一个实例,而且该实例易于供外界访问
2)从而方便地控制了实例个数,并节约系统资源
1)在.m中保留一个全局的static的实例
static id _instance;
2)重写allocWithZone:方法,在这里创建唯一的实例(注意线程安全)
- + (instancetype)allocWithZone:(struct _NSZone *)zone
-
- {
-
- static dispatch_once_t onceToken;
-
- dispatch_once(&onceToken, ^{
-
- _instance = [super allocWithZone:zone];
-
- });
-
- return _instance;
-
- }
- + (instancetype)sharedInstance
-
- {
-
- static dispatch_once_t onceToken;
-
- dispatch_once(&onceToken, ^{
-
- _instance = [[self alloc] init];
-
- });
-
- return _instance;
-
- }
- - (id)copyWithZone:(struct _NSZone *)zone
-
- {
-
- return _instance;
-
- }
具体单例代码:
AlanTool.h
- #import <Foundation/Foundation.h>
-
- @interface AlanTool : NSObject<NSCopying, NSMutableCopying>
-
- //类方法
- //1.方便访问
- //2.标明身份
- //3.注意:share+类名|default + 类名 | share | default | 类名
- +(instancetype)shareTool;
- @end
AlanTool.m
- #import "AlanTool.m"
-
- @implementation AlanTool
-
- //0.提供全局变量
- static AlanTool *_instance;
-
- //1.alloc-->allocWithZone
- +(instancetype)allocWithZone:(struct _NSZone *)zone
- {
- //加互斥锁解决多线程访问安全问题
- // @synchronized(self) {
- // if (_instance == nil) {
- // _instance = [super allocWithZone:zone];
- // }
- // }
-
- //本身就是线程安全的
- static dispatch_once_t onceToken;
- dispatch_once(&onceToken, ^{
- _instance = [super allocWithZone:zone];
- });
-
- return _instance;
- }
-
- //2.提供类方法
- +(instancetype)shareTool
- {
- //1
- //return [[self alloc]init];
- //2
- static dispatch_once_t onceToken;
- dispatch_once(&onceToken, ^{
- _instance = [super allocWithZone:zone];
- });
-
- return _instance;
- }
-
- //3.严谨
- -(id)copyWithZone:(NSZone *)zone
- {
- return _instance;
- }
-
- -(id)mutableCopyWithZone:(NSZone *)zone
- {
- return _instance;
- }
-
- #if __has_feature(objc_arc)
- //条件满足 ARC
- #else
- // MRC
- -(void)release
- {
-
- }
-
- -(instancetype)retain
- {
- return _instance;
- }
-
- //习惯
- -(NSUInteger)retainCount
- {
- return MAXFLOAT;
- }
-
- #endif
-
- @end
- #define SingleH(name) +(instancetype)share##name;
-
- #if __has_feature(objc_arc)
- //条件满足 ARC
- #define SingleM(name) static id _instance;\
- +(instancetype)allocWithZone:(struct _NSZone *)zone\
- {\
- static dispatch_once_t onceToken;\
- dispatch_once(&onceToken, ^{\
- _instance = [super allocWithZone:zone];\
- });\
- \
- return _instance;\
- }\
- \
- +(instancetype)share##name\
- {\
- return [[self alloc]init];\
- }\
- \
- -(id)copyWithZone:(NSZone *)zone\
- {\
- return _instance;\
- }\
- \
- -(id)mutableCopyWithZone:(NSZone *)zone\
- {\
- return _instance;\
- }
-
- #else
- //MRC
- #define SingleM(name) static id _instance;\
- +(instancetype)allocWithZone:(struct _NSZone *)zone\
- {\
- static dispatch_once_t onceToken;\
- dispatch_once(&onceToken, ^{\
- _instance = [super allocWithZone:zone];\
- });\
- \
- return _instance;\
- }\
- \
- +(instancetype)share##name\
- {\
- return [[self alloc]init];\
- }\
- \
- -(id)copyWithZone:(NSZone *)zone\
- {\
- return _instance;\
- }\
- \
- -(id)mutableCopyWithZone:(NSZone *)zone\
- {\
- return _instance;\
- }\
- -(oneway void)release\
- {\
- }\
- \
- -(instancetype)retain\
- {\
- return _instance;\
- }\
- \
- -(NSUInteger)retainCount\
- {\
- return MAXFLOAT;\
- }
- #endif
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。