RunLoop

2015-11-14  本文已影响336人  coma

RunLoop介绍

RunLoop 处理逻辑.png

RunLoop相关类

RunLoop.png
 //1.创建一个NSTimer
     NSTimer *timer = [NSTimer timerWithTimeInterval:1.0 target:self selector:@selector(show) userInfo:nil repeats:YES];
 // 2.将NSTimer添加到RunLoop中, 并且告诉系统, 当前Tiemr只有在RunLoop的默认模式下才有效
     [[NSRunLoop currentRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode];
     
// 2.将NSTimer添加到RunLoop中, 并且告诉系统, 当前Tiemr只有在Tracking的默认模式下才有效
//   [[NSRunLoop currentRunLoop] addTimer:timer forMode:UITrackingRunLoopMode];
     
// 2.将NSTimer添加到RunLoop中, 并且告诉系统, 在所有被"标记"common的模式都可以运行,  
     UITrackingRunLoopMode和kCFRunLoopDefaultMode都被标记为了common模式, 所以只需要  
     将timer的模式设置为forMode:NSRunLoopCommonModes,就可以在默认模式和追踪模式都能够
     运行
     //    [[NSRunLoop currentRunLoop]   addTimer:timer forMode:NSRunLoopCommonModes];
 // 注意: 如果是通过scheduledTimerWithTimeInterval创建的NSTimer, 默认就会添加到
RunLoop得DefaultMode中 , 所以它会自动运行
    NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(show) userInfo:nil repeats:YES];
// 虽然默认已经添加到DefaultMode中, 但是我们也可以自己修改它的模式
    [[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];
- (void)show
{
    NSLog(@"%s", __func__);
}
  // 创建Observer
    /*
     第1个参数: 指定如何给observer分配存储空间
     第2个参数: 需要监听的状态类型/ kCFRunLoopAllActivities监听所有状态
     第3个参数: 是否每次都需要监听
     第4个参数: 优先级
     第5个参数: 监听到状态改变之后的回调
     */
    CFRunLoopObserverRef  observer = CFRunLoopObserverCreateWithHandler(CFAllocatorGetDefault(), kCFRunLoopAllActivities, YES, 0, ^(CFRunLoopObserverRef observer, CFRunLoopActivity activity) {
        switch (activity) {
            case kCFRunLoopEntry:
                NSLog(@"即将进入runloop");
                break;
            case kCFRunLoopBeforeTimers:
                NSLog(@"即将处理timer");
                break;
            case kCFRunLoopBeforeSources:
                NSLog(@"即将处理source");
                break;
            case kCFRunLoopBeforeWaiting:
                NSLog(@"即将进入睡眠");
                break;
            case kCFRunLoopAfterWaiting:
                NSLog(@"刚从睡眠中唤醒");
                break;
            case kCFRunLoopExit:
                NSLog(@"即将退出");
                break;
            default:
                break;
        }
    });
    
    
    // 给主线程的RunLoop添加一个观察者
    /*
     第1个参数: 需要给哪个RunLoop添加观察者
     第2个参数: 需要添加的Observer对象
     第3个参数: 在哪种模式下可以可以监听
     */
    CFRunLoopAddObserver(CFRunLoopGetMain(), observer, kCFRunLoopDefaultMode);
    
    // 释放对象
凡是带有Create、Copy、Retain等字眼的函数,创建出来的对象,都需要在最后做一次release
比如CFRunLoopObserverCreate
release函数:CFRelease(对象);
    CFRelease(observer);
    
    [NSTimer scheduledTimerWithTimeInterval:5.0 target:self selector:@selector(show) userInfo:nil repeats:YES];
- (void)show{
    
}

RunLoop应用场景

- (void)viewDidLoad
{
     //自动释放池什么时候创建和释放
     // 1.第一次创建, 是在runloop进入的时候创建  对应的状态 = kCFRunLoopEntry
     //2.最后一次释放, 是在runloop退出的时候  对应的装 = kCFRunLoopExit
     //3.其它创建和释放
     //每次睡觉的时候都会释放前自动释放池, 然后再创建一个新的
    NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(show) object:nil];
    self.thread = thread;
    [thread start];
}

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    NSLog(@"%s", __func__);
    /*
    // 1.在指定模式下进行特定的操作
    [self.imageView performSelector:@selector(setImage:) withObject:[UIImage imageNamed:@"abc"] afterDelay:2.0 inModes:@[UITrackingRunLoopMode]];
     */
    
    // 默认清空下一个线程只能使用一次, 也就是说只能执行一个操作, 执行完毕之后就不能使用了
    [self performSelector:@selector(test) onThread:self.thread withObject:nil waitUntilDone:YES];
}
- (void)show{
    NSLog(@"%s", __func__);  
    // 1.子线程的NSRunLoop需要手动创建
    // 2.子线程的NSRunLoop需要手动开启
    // 3.如果子线程的NSRunLoop没有设置source or timer, 那么子线程的NSRunLoop会立刻关闭
    //相当于添加了一个基于端口的source
//    [[NSRunLoop currentRunLoop] addPort:[NSMachPort port] forMode:NSDefaultRunLoopMode];
   
//    NSTimer *timer = [NSTimer timerWithTimeInterval:5.0 target:self selector:@selector(test) userInfo:nil repeats:YES];
//    [[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];
//    [[NSRunLoop currentRunLoop] run];
// 注意点: NSRunLoop只会检查有没有source和timer, 没有就关闭, 不会检查observer
    CFRunLoopObserverRef  observer = 
CFRunLoopObserverCreateWithHandler(CFAllocatorGetDefault(), kCFRunLoopAllActivities, YES, 0, ^(CFRunLoopObserverRef observer, CFRunLoopActivity activity) {
    });

    CFRunLoopAddObserver(CFRunLoopGetCurrent(), observer, kCFRunLoopDefaultMode);
    // 释放对象
    CFRelease(observer);
    
    [[NSRunLoop currentRunLoop] run];
    NSLog(@"end -----");
}

- (void)test
{
    NSLog(@"%s %@", __func__, [NSThread currentThread]);
}
上一篇 下一篇

猜你喜欢

热点阅读