iOS-GCD多线程编程详解5
iOS-GCD多线程编程详解5
今天主要讲的函数是dispatch_once,该函数的作用是在程序生命周期范围内只执行提交的block一次,不会在执行第二次。
一.dispatch_once函数
void dispatch_once(dispatch_once_t *predicate, dispatch_block_t block);
参数:
1.predicate:该参数是为了表示该block执行完成或者已经执行,它必须是一个静态的long int 类型的变量
2.block:该block就是只执行一次的任务
使用:
static dispatch_once_t onceToken; NSLog(@"前onceToken=%ld",onceToken); dispatch_once(&onceToken, ^{ NSLog(@"中onceToken%ld",onceToken); NSLog(@"dispatch_once "); }); NSLog(@"后onceToken=%ld",onceToken);
运行结果:
2015-01-10 15:45:00.448 GCDTest[1006:55054] 前onceToken=0
2015-01-10 15:45:00.449 GCDTest[1006:55054] 中onceToken140734785690192
2015-01-10 15:45:00.449 GCDTest[1006:55054] dispatch_once
2015-01-10 15:45:00.449 GCDTest[1006:55054] 后onceToken=-1
使用2:
static dispatch_once_t onceToken; NSLog(@"前onceToken=%ld",onceToken); dispatch_once(&onceToken, ^{ NSLog(@"中onceToken%ld",onceToken); NSLog(@"dispatch_once "); }); dispatch_once(&onceToken, ^{ NSLog(@"中onceToken%ld",onceToken); NSLog(@"dispatch_once "); }); dispatch_once(&onceToken, ^{ NSLog(@"中onceToken%ld",onceToken); NSLog(@"dispatch_once "); }); NSLog(@"后onceToken=%ld",onceToken);
运行结果:
2015-01-10 15:54:42.682 GCDTest[1047:58632] 前onceToken=0
2015-01-10 15:54:42.683 GCDTest[1047:58632] 中onceToken140734613617216
2015-01-10 15:54:42.683 GCDTest[1047:58632] dispatch_once
2015-01-10 15:54:42.683 GCDTest[1047:58632] 后onceToken=-1
不管block被提交了多少次都只是被执行一次。onceToken的前后的值是0和-1,运行中为随机数,
使用3:
static dispatch_once_t onceToken; static dispatch_once_t onceToken2; static dispatch_once_t onceToken3; NSLog(@"前onceToken=%ld",onceToken); NSLog(@"前onceToken2=%ld",onceToken2); NSLog(@"前onceToken3=%ld",onceToken3); dispatch_once(&onceToken, ^{ NSLog(@"中onceToken%ld",onceToken); NSLog(@"dispatch_once "); }); dispatch_once(&onceToken2, ^{ NSLog(@"中onceToken2%ld",onceToken2); NSLog(@"dispatch_once "); }); dispatch_once(&onceToken3, ^{ NSLog(@"中onceToken3%ld",onceToken3); NSLog(@"dispatch_once "); }); NSLog(@"后onceToken=%ld",onceToken); NSLog(@"后onceToken2=%ld",onceToken2); NSLog(@"后onceToken3=%ld",onceToken3);
运行结果:
2015-01-10 15:58:26.562 GCDTest[1091:60066] 前onceToken=0
2015-01-10 15:58:26.563 GCDTest[1091:60066] 前onceToken2=0
2015-01-10 15:58:26.563 GCDTest[1091:60066] 前onceToken3=0
2015-01-10 15:58:26.563 GCDTest[1091:60066] 中onceToken140734702901808
2015-01-10 15:58:26.563 GCDTest[1091:60066] dispatch_once
2015-01-10 15:58:26.563 GCDTest[1091:60066] 中onceToken2140734702901808
2015-01-10 15:58:26.563 GCDTest[1091:60066] dispatch_once
2015-01-10 15:58:26.563 GCDTest[1091:60066] 中onceToken3140734702901808
2015-01-10 15:58:26.564 GCDTest[1091:60066] dispatch_once
2015-01-10 15:58:26.564 GCDTest[1091:60066] 后onceToken=-1
2015-01-10 15:58:26.564 GCDTest[1091:60066] 后onceToken2=-1
2015-01-10 15:58:26.564 GCDTest[1091:60066] 后onceToken3=-1
从几种使用及其结果来看,只执行一次是有predicte参数来表示,为0表示未被执行,为-1表示执行了,被它表示的就不会被执行第二次。
二.实际编程中的应用
既然提交的block为在程序中只运行一次,那么如果你想那个类,对象,函数只被初始化一次只被实例化一次只被执行一次,你就可以把它包含到block中并通过该函数提交掉用。
在设计模式中单例模式是比较常用的,整个程序 中只有这类的一个静态实例变量,所以我们就可以通过该函数来实现一个单例的类。
1.新建一个类SingleObject
#import <Foundation/Foundation.h> @interface SingleObject : NSObject +(SingleObject *)shareObject; @end
@implementation SingleObject +(SingleObject *)shareObject{ static SingleObject *_share =nil; static dispatch_once_t predicate; dispatch_once(&predicate, ^{ if (!_share) { _share = [[SingleObject alloc]init]; } }); return _share; } @end
单例的使用:
#import "ViewController.h" #import "SingleObject.h" @interface ViewController () @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; for (int i=0; i<5; i++) { NSLog(@"第%d次---%@",i,[SingleObject shareObject]); } } @end
运行结果分析:
1:
2015-01-10 16:11:09.336 GCDTest[1129:63127] 第0次---<SingleObject: 0x7f8ce3737390>
2015-01-10 16:11:09.337 GCDTest[1129:63127] 第1次---<SingleObject: 0x7f8ce3737390>
2015-01-10 16:11:09.338 GCDTest[1129:63127] 第2次---<SingleObject: 0x7f8ce3737390>
2015-01-10 16:11:09.338 GCDTest[1129:63127] 第3次---<SingleObject: 0x7f8ce3737390>
2015-01-10 16:11:09.338 GCDTest[1129:63127] 第4次---<SingleObject: 0x7f8ce3737390>
2:2015-01-10 16:13:55.572 GCDTest[1154:64460] 第0次---<SingleObject: 0x7fff0bc61e80>
2015-01-10 16:13:55.573 GCDTest[1154:64460] 第1次---<SingleObject: 0x7fff0bc61e80>
2015-01-10 16:13:55.573 GCDTest[1154:64460] 第2次---<SingleObject: 0x7fff0bc61e80>
2015-01-10 16:13:55.573 GCDTest[1154:64460] 第3次---<SingleObject: 0x7fff0bc61e80>
2015-01-10 16:13:55.573 GCDTest[1154:64460] 第4次---<SingleObject: 0x7fff0bc61e80>
3:2015-01-10 16:14:16.088 GCDTest[1162:64744] 第0次---<SingleObject: 0x7fb1a04494b0>
2015-01-10 16:14:16.088 GCDTest[1162:64744] 第1次---<SingleObject: 0x7fb1a04494b0>
2015-01-10 16:14:16.088 GCDTest[1162:64744] 第2次---<SingleObject: 0x7fb1a04494b0>
2015-01-10 16:14:16.088 GCDTest[1162:64744] 第3次---<SingleObject: 0x7fb1a04494b0>
2015-01-10 16:14:16.089 GCDTest[1162:64744] 第4次---<SingleObject: 0x7fb1a04494b0>
几次运行的结果都是指向相同的一个对象。
小结读者可以根据自己的需求使用该函数,在程序中只使用一次。