RunLoop使用方法

RunLoop使用方法

 - (void)viewDidLoad {
    [super viewDidLoad];
    
    self.thread = [[NSThread alloc] initWithTarget:self selector:@selector(execute) object:nil];
    [self.thread start];
    
}
    
- (void)run
{
    NSLog(@"----------run----%@", [NSThread currentThread]);
    
    // 需要向runloop中加入timer/source(Port)/observer等runloop才不会退出
    [[NSRunLoop currentRunLoop] addPort:[NSPort port] forMode:NSDefaultRunLoopMode];
    [[NSRunLoop currentRunLoop] run];
}
// 调用该方法随时可以进入runloop执行操作
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    [self performSelector:@selector(test) onThread:self.thread withObject:nil waitUntilDone:NO];
}

// 此方法也可以保持runloop
- (void)execute
{
    // scheduledTimer这个方法把timer直接加进runloop了,不需要手动添加
    [NSTimer scheduledTimerWithTimeInterval:2.0 target:self selector:@selector(test) userInfo:nil repeats:YES];
    [[NSRunLoop currentRunLoop] run];
    
    // 此种方法需要自己添加到runloop中启动
    NSTimer *timer = [NSTimer timerWithTimeInterval:2.0 target:self selector:@selector(run) userInfo:nil repeats:YES];
    [[NSRunLoop currentRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode];
    [[NSRunLoop currentRunLoop] run];

}

- (void)timer {
    
    //调用scheduledTimer返回的定时器,已经自动被添加到当前runloop中,而且是NSDefaultRunLoopMode
//    [NSTimer scheduledTimerWithTimeInterval:2.0 target:self selector:@selector(run) userInfo:nil repeats:YES];
    
    NSTimer *timer = [NSTimer timerWithTimeInterval:2.0 target:self selector:@selector(run) userInfo:nil repeats:YES];
    
    //定时器只运行在NSDefaultRunLoopMode下,一旦RunLoop进入其他模式,这个定时器就不会工作
    //[[NSRunLoop currentRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode];
    
    //定时器只运行在UITrackingRunLoopMode下,一旦RunLoop进入其他模式,这个定时器就不会工作
    //[[NSRunLoop currentRunLoop] addTimer:timer forMode:UITrackingRunLoopMode];
    
    //定时器在NSRunLoopCommonModes下,两种模式下都可以工作
    [[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];
}

- (void)observer{
    
    //添加observer
    /*
     activity的状态值
     kCFRunLoopEntry = (1UL << 0), 1 即将进入runloop
     kCFRunLoopBeforeTimers = (1UL << 1), 2 即将处理timer
     kCFRunLoopBeforeSources = (1UL << 2), 4 即将处理Source
     kCFRunLoopBeforeWaiting = (1UL << 5), 32 即将进入休眠
     kCFRunLoopAfterWaiting = (1UL << 6),  64  刚从休眠中唤醒
     kCFRunLoopExit = (1UL << 7),           128 即将退出runloop
     kCFRunLoopAllActivities = 0x0FFFFFFFU
     可以监听按钮点击之前的时间
     */
    CFRunLoopObserverRef observer = CFRunLoopObserverCreateWithHandler(CFAllocatorGetDefault(), kCFRunLoopAllActivities, YES, 0, ^(CFRunLoopObserverRef observer, CFRunLoopActivity activity) {
        NSLog(@"-----监听到runloop状态发生改变%zd",activity);
    });
    
    
    // 添加观察者,监听Runloop的状态
    CFRunLoopAddObserver(CFRunLoopGetCurrent(), observer, kCFRunLoopDefaultMode);
    
    // 释放observer
    CFRelease(observer);
    
    /*
     CF的内存管理
     1.凡是带有create、copy、retain等字眼的函数,创建出来的对象 最后要做一次release
     2、release函数,CFRelease(observer)
     
     */
    
}


RunLoop面试题

  • 什么是RunLoop

  • 从字面意思看,就是运行循环、跑圈

  • 其实它内部就是do-while循环,在这个循环内部不断处理各种任务(比如Source、Timer、Observer)

  • 一个线程对应一个runloop,主线程的runloop默认已经启动,子线程的 runloop得手动启动,调用run方法

  • runloop只能选择一个Model启动,如果当前model中没有Source、timer、observer,那么就直接退出runloop

  • 自动释放池什么时候释放?

  • 在RunLoop睡眠之前释放(BeforeWaiting)

  • 在开发中如何使用RunLoop?什么应用场景?
    开启一个常驻线程,让一个子线程不进入消亡状态,等待其他线程发来消息,处理事件,比如:

  • 在子线程中开启一个定时器

  • 在子线程中进行一些长期监控

  • 可以控制定时器在特定模式下执行

  • 让某些事件在特定模式下执行

  • 可以添加observer监听RunLoop的状态,比如监听点击事件的处理

你可能感兴趣的:(RunLoop使用方法)