gpt4 book ai didi

ios - dispatch_after block 未运行

转载 作者:行者123 更新时间:2023-12-01 19:38:37 26 4
gpt4 key购买 nike

请考虑以下简单示例:

- (void)viewDidLoad
{
[super viewDidLoad];

dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{

dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
NSLog(@"BLOCK!!!");

});

while (YES)
{
[[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate dateWithTimeIntervalSinceNow:1]];
NSLog(@"RUN LOOP");
}
});
}

传递到 dispatch_after的第二个调用(3秒)中的块不会触发。但是,如果我不使用第一个 dispatch_after(2秒),那么它将按预期工作。为什么?

我知道,如果我在内部运行 NSRunLoop的情况下删除了while循环,则它可以正常工作,但是我需要在那儿循环

最佳答案

你有哪个代码

  • 安排dispatch_after在主队列上运行;但是然后
  • 通过while循环阻塞主队列,该循环反复调用NSRunLoop

  • 这只是阻止主线程执行任何未直接从 NSRunLoop主调用的操作。

    解决此问题的方法有三种:
  • 您可以通过将带有while循环的代码调度到全局(即后台)队列来解决此问题:
    - (void)viewDidLoad{
    [super viewDidLoad];

    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_global_queue(QOS_CLASS_DEFAULT, 0), ^{
    NSLog(@"OUTER");

    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
    NSLog(@"INNER!!!");
    });

    while (true) {
    [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate dateWithTimeIntervalSinceNow:1]];
    }
    });
    }

    这种技术是我们在GCD之前的日子所做的一种排列。如今,这在很大程度上变得毫无用处。效率太低了。
  • 您可以使用从NSTimer计划并运行的NSRunLoop,因此,尽管您仍在阻止主队列,但至少会触发计时器。
    - (void)viewDidLoad{
    [super viewDidLoad];

    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
    NSLog(@"OUTER");

    [NSTimer scheduledTimerWithTimeInterval:3 repeats:false block:^(NSTimer * _Nonnull timer) {
    NSLog(@"INNER!!!");
    }];

    while (true) {
    [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate dateWithTimeIntervalSinceNow:1]];
    }
    });
    }

    这并不是解决问题的真正方法(您仍在阻止主线程阻止未从NSRunLoop本身运行的任何操作),但可以说明运行循环的性质。
  • 或者,显然,最好只是删除while循环:
    - (void)viewDidLoad{
    [super viewDidLoad];

    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
    NSLog(@"OUTER");

    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
    NSLog(@"INNER!!!");
    });
    });
    }

  • 最重要的是,如今,您几乎永远不会在线程(或其运行循环)上旋转。它效率极低,GCD提供了更为优雅的方法来达到预期的效果。

    关于ios - dispatch_after block 未运行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58713976/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com