iOS开发过程中经常遇到的GCD的一些问题

iOS开发过程中经常遇到的GCD的一些问题

目录

前言

1.performSelector相关的一个问题

2.一个崩溃问题


前言

        记录GCD使用过程中遇到的一个小问题。

1.performSelector相关的一个问题

        输入下面代码的打印结果:

- (void)viewDidLoad {
    [super viewDidLoad];
    [self gcdDemos01];
}
- (void)gcdDemos01{
    dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
    dispatch_async(queue, ^{
        NSLog(@"do task1");
        [self performSelector:@selector(test) withObject:nil afterDelay:0];
        NSLog(@"do task3");

    });
}
- (void)test{
    NSLog(@"do task2");
}

        想一下运行之后控制台如何输出:

图1.GCD控制台打印结果

        这里的

- (void)performSelector:(SEL)aSelector withObject:(nullable id)anArgument afterDelay:(NSTimeInterval)delay;

的底层其实是往Runloop中添加了一个定时器,但是默认情况下子线程中的RunLoop是没有启动的。

        这里如果想要执行test方法,则需要我们手动启动RunLoop。

        修改之后的代码如下:

    [super viewDidLoad];

    [self gcdDemos01];

}

- (void)gcdDemos01{

    dispatch_queue_t queue = dispatch_get_global_queue(0, 0);

    dispatch_async(queue, ^{

        NSLog(@"do task1");

        [self performSelector:@selector(test) withObject:nil afterDelay:0];

        NSLog(@"do task3");

        [[NSRunLoop currentRunLoop] addPort:[[NSPort alloc]init] forMode:NSDefaultRunLoopMode];

        [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];

    });

}

- (void)test{

    NSLog(@"do task2");

}

        这个时候运行代码,控制台的打印信息如下:

图2.手动启动RunLoop

        iOS中还有一个类似的方法,就是

- (id)performSelector:(SEL)aSelector withObject:(id)object;

        这个方法底层就是基于Runtime实现的。调用的是msgSend方法。

        我们把上述代码中的方法替换一下,也可以实现test的方法的打印功能。

- (void)viewDidLoad {
    [super viewDidLoad];
    [self gcdDemos01];
}
- (void)gcdDemos01{
    dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
    dispatch_async(queue, ^{
        NSLog(@"do task1");
        [self performSelector:@selector(test) withObject:nil];
        NSLog(@"do task3");
    });
}
- (void)test{
    NSLog(@"do task2");
}

2.一个崩溃问题

        看一下下面代码的打印结果:

- (void)test{
    NSLog(@"do task2");
}
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
    NSThread * thread = [[NSThread alloc]initWithBlock:^{
        NSLog(@"do task1");
    }];
    [thread start];
    [self performSelector:@selector(test) onThread:thread withObject:nil waitUntilDone:YES];
}

        仔细思考下你想象中的结果。

        控制台打印如下:

图2.控制台输出结果

        这里thread执行完打印任务之后,线程就退出了。退出之后,有在这个线程上执行了test方法,一次崩溃了。

        解决的方案和第一个问题一样,我们手动启动下RunLoop即可。

转载请说明出处内容投诉
CSS教程网 » iOS开发过程中经常遇到的GCD的一些问题

发表评论

欢迎 访客 发表评论

一个令你着迷的主题!

查看演示 官网购买