08 - 多线程 - 03:performSelector:withObject:afterDelay:方法

总结

  1. 面试题:在 GCD 中调用 performSelector:withObject:afterDelay: 方法,打印结果是什么?
  2. performSelector:withObject:afterDelay: 方法 和 performSelector:withObject: 方法 的区别

面试题:

面试题:在 GCD 中调用 performSelector:withObject:afterDelay: 方法,打印结果是什么?

// 全局并发队列
dispatch_queue_t queue = dispatch_Get_global_queue(0,0);
// 异步任务  
dispatch_async(queue, ^{
	NSLog(@"1");
	[self performSelector:@selector(test) withObject:nil afterDelay: .0];
	NSLog(@"3");
});

- (void) test {
	NSLog(@"2");
}
  • 打印结果是:1、3
  • 为什么没有打印2?原因:
    • performSelector:withObject:afterDelay:的本质是往Runloop中添加定时器
    • 而子线程默认没有启动Runloop

一、方法的含义

    [self performSelector:@selector(test) withObject:nil afterDelay:3.0];
  • 含义:三秒以后,调用 self的 test 方法
  • afterDelay 后面 可以写 “.0” :表示 0秒以后执行 self的 test 方法

二、performSelector:withObject:afterDelay: 方法

  1. GCD 中写 performSelector:withObject:afterDelay: 方法
 dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
    
    dispatch_async(queue, ^{
        NSLog(@"1");
        [self performSelector:@selector(test) withObject:nil afterDelay:0.0];
        NSLog(@"3");
    });

打印结果:
1
3

test 没有 被调用。

  1. 在主线程中 调用此方法
- (void)viewDidLoad {
    [super viewDidLoad];
    
    NSLog(@"1");
    [self performSelector:@selector(test) withObject:nil afterDelay:0.3];
    NSLog(@"3");
}

打印结果:
1
3
2

  1. performSelector:withObject:afterDelay: 的底层
  • 不在 NSObject 中,而是在NSRunLoop 类中
  • 带有 afterDelay 的方法,都是在 NSRunLoop 类中定义的
  1. 为何在 主线程就可以调用 test 方法,在GCD 中却不能调用 test 方法?
  • 这是因为 performSelector:withObject:afterDelay: 类的底层调用了 NSTimer 定时器。
  • 定时器是要添加到 runloop 中去的。
  • 这句话的底层就是 往 runloop 中添加了一个定时器。
  • 主线程 默认有 runloop,所以 在主线程 可以调用 test方法。
  • 而 GCD 中没有 runloop ,所以 不会调用 test 方法。如果想要在 GCD 中调用 test 方法,需要自己开启 runloop 。

完整代码:
在这里插入图片描述
打印结果:
1
3
2


三、performSelector:withObject: 方法

  1. 在 GCD 中调用 此方法
    dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
    
    dispatch_async(queue, ^{
        NSLog(@"1");
        [self performSelector:@selector(test) withObject:nil];
        NSLog(@"3");
    });
    

打印结果:
1
2
3

  1. performSelector:withObject: 的底层代码
    在这里插入图片描述
  • performSelector:withObject: 是在 NSObject 中定义的;
  • [self performSelector:@selector(test) withObject:nil] 会在底层转换为 objcMsgSend(self, @selector(test)).

四、GNUstep

五、了解 GNUstep 中 performSelector:withObject:afterDelay: 的底层

  • base项目 -> source 文件夹 -> Foundation 文件夹 -> NSRunLoop.m

  • 找到 performSelector:withObject:afterDelay: 方法
    在这里插入图片描述

    • 创建一个 runloop
    • 创建一个 time
    • 把 time 添加到 runloop 中
  • initWithSelector: target: argument: delay: 方法
    在这里插入图片描述

这里面 只有创建 runloop ,没有启动runloop ,所以需要自己启动runloop。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值