0
点赞
收藏
分享

微信扫一扫

iOS 利用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----

参考资料

iOS开发-阻塞主线程
IOS 等待条件满足再向下执行但不主卡线程NSRunLoop

举报

相关推荐

0 条评论