这里的阻塞主线程,并不是真正的卡死,而是利用
runloop
让主线程等待。
举例:我有三个方法需要依次执行testLogOne
testLogTwo
testLogThree
,但是方法二testLogTwo
中是有block
或者是block 中有返回值的
,方法三testLogThree
需要等待方法二的block
回调完成后才能执行。
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
[self testLogOne];
[self testLogTwo:^{
NSLog(@"----2----");
}];
[self testLogThree];
}
/// 方法一
- (void)testLogOne {
NSLog(@"----1----");
}
/// 方法二
/// @param twoBlock 回调
- (void)testLogTwo:(void(^)(void))twoBlock {
dispatch_async(dispatch_get_main_queue(), ^{
if (twoBlock) {
twoBlock();
}
});
}
/// 方法三
- (void)testLogThree {
NSLog(@"----3----");
}
控制台输出
2021-03-16 18:04:41.691889+0800 demo[45188:559343] ----1----
2021-03-16 18:04:41.692060+0800 demo[45188:559343] ----3----
2021-03-16 18:04:41.714916+0800 demo[45188:559343] ----2----
使用信号量dispatch_semaphore_t ❌
使用信号量dispatch_semaphore_t
会直接卡死主线程,永远等待不到信号的的接收。
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
/// 卡主线程
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
[self testLogOne];
[self testLogTwo:^{
NSLog(@"----2----");
dispatch_semaphore_signal(semaphore);
}];
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
[self testLogThree];
}
使用dispatch_group_t ⁉️
使用dispatch_group_t
也可以将方法三testLogThree
,放到dispatch_group_notify
中执行,但是,考虑到实际情况下,其他方法可能要比方法三testLogThree
先执行,所有也放弃了此用法的考虑。虽然可以将方法三testLogThree
放到block
中,但是如果有其他特殊情况,例如for循环
,这样也是不可取的。
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
dispatch_group_t group = dispatch_group_create();
[self testLogOne];
for (NSInteger i = 0; i < 10; i ++) {
dispatch_group_enter(group);
[self testLogTwo:^{
NSLog(@"----2----");
dispatch_group_leave(group);
}];
}
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
NSLog(@"----2----after");
//[self testLogThree];
});
[self testLogThree];
}
控制台输出
2021-03-16 18:15:47.571770+0800 demo[48810:577013] ----1----
2021-03-16 18:15:47.572034+0800 demo[48810:577013] ----3----
2021-03-16 18:15:47.588403+0800 demo[48810:577013] ----2----
2021-03-16 18:15:47.588557+0800 demo[48810:577013] ----2----
2021-03-16 18:15:47.588653+0800 demo[48810:577013] ----2----
2021-03-16 18:15:47.588736+0800 demo[48810:577013] ----2----
2021-03-16 18:15:47.588830+0800 demo[48810:577013] ----2----
2021-03-16 18:15:47.588919+0800 demo[48810:577013] ----2----
2021-03-16 18:15:47.589213+0800 demo[48810:577013] ----2----
2021-03-16 18:15:47.589303+0800 demo[48810:577013] ----2----
2021-03-16 18:15:47.589590+0800 demo[48810:577013] ----2----
2021-03-16 18:15:47.589831+0800 demo[48810:577013] ----2----
2021-03-16 18:15:47.590538+0800 demo[48810:577013] ----2----after
使用runloop ✅
运行runLoop
一次,阻塞当前线程以等待处理。根据条件进行while循环
,达到条件后runloop
退出
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
__block BOOL isPerformNextStep = NO;
[self testLogOne];
for (NSInteger i = 0; i < 10; i ++) {
[self testLogTwo:^{
NSLog(@"----2----");
isPerformNextStep = YES;
}];
}
while (!isPerformNextStep) {
[[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
}
[self testLogThree];
}
控制台输出:
2021-03-16 18:30:12.403732+0800 demo[54758:602699] ----1----
2021-03-16 18:30:12.407238+0800 demo[54758:602699] ----2----
2021-03-16 18:30:12.407371+0800 demo[54758:602699] ----2----
2021-03-16 18:30:12.407472+0800 demo[54758:602699] ----2----
2021-03-16 18:30:12.407554+0800 demo[54758:602699] ----2----
2021-03-16 18:30:12.407631+0800 demo[54758:602699] ----2----
2021-03-16 18:30:12.407726+0800 demo[54758:602699] ----2----
2021-03-16 18:30:12.407801+0800 demo[54758:602699] ----2----
2021-03-16 18:30:12.407909+0800 demo[54758:602699] ----2----
2021-03-16 18:30:12.408005+0800 demo[54758:602699] ----2----
2021-03-16 18:30:12.408137+0800 demo[54758:602699] ----2----
2021-03-16 18:30:12.408383+0800 demo[54758:602699] ----3----