个人对RunLoop的见解

RunLoop–运行环

  • RunLoop的基本作用
    • 保持程序的持续运行
    • 处理app中的各种事件(比如触摸事件,定时器事件,selector事件)
    • 节省CPU资源,提高程序性能:该做事的时候做事,该休息就休息
  • main函数中的RunLoop
    • UIApplication函数内部就启动了一个RunLoop
    • 这个Runloop主线程的,默认是开启的,子线程的RunLoop默认是关闭的
    • 每条线程都有唯一与之对应的RunLoop对象
  • ios中2套API来访问和使用RunLoop
    • NSRunLoop(NSRunLoop -> oc)
    • CFRunLoopRef(Core Foundation -> c)
  • RunLoop对象的获取
    • Foundation中
      objc
      [NSRunLoop currentRunLoop];//获取当前线程的RunLoop对象
      [NSRunLoop mainRunLoop];//获取主线程的RunLoop对象
    • Core Foundation中
      objc
      CFRunLoopGetCurrent();//获取当前线程的RunLoop
      CFRunLoopGetMain();//获取主线程的RunLoop对象
  • RunLoopMode 系统默认注册了5个mode

    • kCFRunLoopDefaultMode:App的默认Mode,通常主线程是在这个Mode下运行

    • UITrackingRunLoopMode:界面跟踪 Mode,用于 ScrollView 追踪触摸滑动,保证界面滑动时不受其他 Mode 影响

    • UIInitializationRunLoopMode: 在刚启动 App 时第进入的第一个 Mode,启动完成后就不再使用

    • GSEventReceiveRunLoopMode: 接受系统事件的内部 Mode,通常用不到

    • kCFRunLoopCommonModes: 这是一个占位用的Mode,不是一种真正的Mode

  • CFRunLoopObserverRef
    typedef CF_OPTIONS(CFOptionFlags, CFRunLoopActivity)
    {
        kCFRunLoopEntry = (1UL << 0), //即将进入loop
        kCFRunLoopBeforeTimers = (1UL << 1),//即将处理Timer
        kCFRunLoopBeforeSources = (1UL << 2),//即将处理Source
        kCFRunLoopBeforeWaiting = (1UL << 5),//即将进入休眠
        kCFRunLoopAfterWaiting = (1UL << 6),///刚从休眠中唤醒
        kCFRunLoopExit = (1UL << 7),//即将推出loop
        kCFRunLoopAllActivities = 0x0FFFFFFFU//
    };
  • RunLoop处理逻辑
    这里写图片描述
  • 监听RunLoop的状态
 // 创建observer
    CFRunLoopObserverRef observer = CFRunLoopObserverCreateWithHandler(CFAllocatorGetDefault(), kCFRunLoopAllActivities, YES, 0, ^(CFRunLoopObserverRef observer, CFRunLoopActivity activity) {
        NSLog(@"----监听到RunLoop状态发生改变---%zd", activity);
    });

    // 添加观察者:监听RunLoop的状态
    CFRunLoopAddObserver(CFRunLoopGetCurrent(), observer, kCFRunLoopDefaultMode);

    // 释放Observer
    CFRelease(observer);
  • GCD定时器
    • 优势:不受RunLoop的影响,计时更加准确,稳定性好
  // 获得队列
    dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
//    dispatch_queue_t queue = dispatch_get_main_queue();

    // 创建一个定时器(dispatch_source_t本质还是个OC对象)
    self.timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);

    // 设置定时器的各种属性(几时开始任务,每隔多长时间执行一次)
    // GCD的时间参数,一般是纳秒(1秒 == 10的9次方纳秒)
    // 何时开始执行第一个任务
    // dispatch_time(DISPATCH_TIME_NOW, 1.0 * NSEC_PER_SEC) 比当前时间晚3秒
    dispatch_time_t start = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0 * NSEC_PER_SEC));
    uint64_t interval = (uint64_t)(1.0 * NSEC_PER_SEC);
    dispatch_source_set_timer(self.timer, start, interval, 0);

    // 设置回调
    dispatch_source_set_event_handler(self.timer, ^{
        NSLog(@"------------%@", [NSThread currentThread]);
        count++;

//        if (count == 4) {
//            // 取消定时器
//            dispatch_cancel(self.timer);
//            self.timer = nil;
//        }
    });

    // 启动定时器
    dispatch_resume(self.timer);
  • RunLoop的应用

    • NSTimer
    • ImageView显示
    • 就是在滑动界面的时候停止图片的刷新,保证了界面的流畅性
    • PerformSelector
    • 常驻线程
    • 自动释放池
  • 常驻线程

- (void)viewDidLoad {
    [super viewDidLoad];

    self.thread = [[XMGThread alloc] initWithTarget:self selector:@selector(execute) object:nil];
    [self.thread start];
}

- (void)execute
{
    NSLog(@"----------run----%@", [NSThread currentThread]);
    //默认线程子线程处理完事件之后机会被回收,但通过向当前的RunLoop添加port之后,使之能够一直运行,保证当前线程不死.RunLoop有Timer,source才能运行
    [[NSRunLoop currentRunLoop] addPort:[NSPort port] forMode:NSDefaultRunLoopMode];
    [[NSRunLoop currentRunLoop] run];
    NSLog(@"---------");
}

- (void)test
{
    NSLog(@"----------test----%@", [NSThread currentThread]);
}

- (void)test2
{
    NSLog(@"***********test2*******%@", [NSThread currentThread]);
}

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    [self performSelector:@selector(test2) onThread:self.thread withObject:nil waitUntilDone:NO];
}
  • RunLoop和自动释放池
kCFRunLoopEntry; // 创建一个自动释放池
kCFRunLoopBeforeWaiting; // 销毁自动释放池,创建一个新的自动释放池
kCFRunLoopExit; // 销毁自动释放池
  • ImageView显示
// 只在NSDefaultRunLoopMode模式下显示图片
    [self.imageView performSelector:@selector(setImage:) withObject:[UIImage imageNamed:@"placeholder"] afterDelay:3.0 inModes:@[NSDefaultRunLoopMode]];
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值