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即可。

  • 16
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

我叫柱子哥

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值