Objective-C中理论知识今日看点程序员

RunLoop由浅到深,个人小结

2016-12-17  本文已影响240人  小白文_Vincent
文艺求关注.png
int main(int argc, char * argv[]) {
    @autoreleasepool {
        return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
    }
}



- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
    [[[NSThread alloc] initWithTarget:self selector:@selector(run) object:nil] start];
}

- (void) run {
    // 如何创建子线程对应的RunLoop,比较奇葩
    // currentRunLoop本身是懒加载,会在第一次调用的时候判断是否存在,如不存在,自动创建
    NSLog(@"%@", [NSRunLoop currentRunLoop]);
    NSLog(@"run ---------- %@", [NSThread currentThread]);
}

RunLoop5各类对应关系.png

<b>* 注意点:</b>


- (void)timer {
    // 1.创建定时器
    NSTimer *timer = [NSTimer timerWithTimeInterval:2.0 target:self selector:@selector(run) userInfo:nil repeats:YES];
    /**
     2.添加定时器到RunLoop中,指定runLoop的运行模式
     @param NSTimer 定时器
     @param Mode runLoop的运行模式
     */
    [[NSRunLoop currentRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode];
    //UITrackingRunLoopMode: 界面追踪
    [[NSRunLoop currentRunLoop] addTimer:timer forMode:UITrackingRunLoopMode];
    //NSRunLoopCommonModes = NSDefaultRunLoopMode + UITrackingRunLoopMode
    //占用,标签,凡是添加到NSRunLoopCommonModes中的事件都会被同时添加到打上common的运行模式上
    /**
     0 : <CFString 0x10af41270 [0x10a0457b0]>{contents =
         "UITrackingRunLoopMode"}
     2 : <CFString 0x10a065b60 [0x10a0457b0]>{contents = "kCFRunLoopDefaultMode"}
     */
    [[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];  
}
- (void) run {
    NSLog(@"run -----------%@------%@", [NSThread currentThread], [NSRunLoop currentRunLoop]);
}
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
    [NSThread detachNewThreadSelector:@selector(timer) toTarget:self withObject:nil];
}
- (void)timer {
    
    // 如果是在子线程中使用此timer创建方式,则需要手动创建runLoop
    NSRunLoop *currentRunLoop = [NSRunLoop currentRunLoop];
    
    // 该方法内部自动添加到runLoop中,并且设置运行模式为默认
    [NSTimer scheduledTimerWithTimeInterval:2.0 target:self selector:@selector(run) userInfo:nil repeats:YES];
    
    // 子线程中创建runLoop之后不会执行,需要手动开启runLoop
    [currentRunLoop run];
}

@property (nonatomic, strong) dispatch_source_t timer;

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {

    /**
     01.创建GCD中的定时器
     @param DISPATCH_SOURCE_TYPE_TIMER source的类型,表示是定时器
     @param 0 描述信息,线程ID
     @param 0 更详细的描述信息
     @param dispatchQueue 队列,确定GCD定时器中的任务在哪个线程中执行
     */
    dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, dispatch_get_global_queue(0, 0));
    
    /**
     02.设置定时器(起始时间|间隔时间|精准度)
     @param timer 定时器对象
     @param DISPATCH_TIME_NOW 起始时间,DISPATCH_TIME_NOW 从现在开始计时
     @param intervalInSeconds * NSEC_PER_SEC 间隔时间
     @param leewayInSeconds * NSEC_PER_SEC 精准度,绝对精准0
     */
    dispatch_source_set_timer(timer, DISPATCH_TIME_NOW, 2.0 * NSEC_PER_SEC, 0 * NSEC_PER_SEC);
    
    // 03.设置定时器执行的任务
    dispatch_source_set_event_handler(timer, ^{
        NSLog(@"------------%@", [NSThread currentThread]);
    });
    
    // 04.启动执行
    dispatch_resume(timer);
    
    self.timer = timer;
}


- (void) observer {
    /**
     // 01.创建监听者
     @param allocator 制定如何分配存储空间
     @param activities 要监听的状态 kCFRunLoopAllActivities 所有状态
     @param repeats 是否持续监听
     @param order 优先级,总是传0
     @param observer activity 当状态改变的时候回调
     */
    CFRunLoopObserverRef observer = CFRunLoopObserverCreateWithHandler(CFAllocatorGetDefault(), kCFRunLoopAllActivities, YES, 0, ^(CFRunLoopObserverRef observer, CFRunLoopActivity activity) {
        /**
         kCFRunLoopEntry = (1UL << 0),          //即将进入runLoop
         kCFRunLoopBeforeTimers = (1UL << 1),   //即将处理timer事件
         kCFRunLoopBeforeSources = (1UL << 2),  //即将处理sources事件
         kCFRunLoopBeforeWaiting = (1UL << 5),  //即将进入睡眠
         kCFRunLoopAfterWaiting = (1UL << 6),   //被唤醒
         kCFRunLoopExit = (1UL << 7),           //runloop推出
         kCFRunLoopAllActivities = 0x0FFFFFFFU  //所有状态
         */
        switch (activity) {
            case kCFRunLoopEntry:
                NSLog(@"即将进入runLoop");
                break;
            case kCFRunLoopBeforeTimers:
                NSLog(@"即将处理timer事件");
                break;
            case kCFRunLoopBeforeSources:
                NSLog(@"即将处理sources事件");
                break;
            case kCFRunLoopBeforeWaiting:
                NSLog(@"即将进入睡眠");
                break;
            case kCFRunLoopExit:
                NSLog(@"runloop推出" );
                break;
            case kCFRunLoopAllActivities:
                NSLog(@"所有状态");
                break;
            default:
                break;
        }
    });
}



@property (nonatomic, strong) NSThread *thread;
// 在storyboard中有两个按钮,创建线程、让线程继续执行任务
//需求:如何保证子线程不挂掉,同时执行其他任务
- (IBAction)creatThreadBtnClick:(id)sender {
    // 01.创建线程
    self.thread = [[NSThread alloc] initWithTarget:self selector:@selector(task1) object:nil];
    [self.thread start];
}
- (void)task1 {
    NSLog(@"task1-----------%@", [NSThread currentThread]);
// 解决方法(保证子线程不挂掉,同时执行其他任务):RunLoop
NSRunLoop *runLoop = [NSRunLoop currentRunLoop];
    //保证RunLoop不退出
    // 方法一:添加Timer
    NSTimer *timer = [NSTimer timerWithTimeInterval:2.0 target:self selector:@selector(runOperation) userInfo:nil repeats:YES];
    [runLoop addTimer:timer forMode:NSDefaultRunLoopMode];
    // 方法二:添加Source
    [runLoop addPort:[NSPort port] forMode:NSDefaultRunLoopMode];
    [runLoop run];
    [runLoop runUntilDate:[NSDate dateWithTimeIntervalSinceNow:10]];    // 给runLoop设置时间,10秒钟后runLoop自动退出,(该设置只针对于子线程中的runLoop有用,对主线程中的runLoop没有任何作用)
    NSLog(@"--------end---------"); // 10秒钟之后打印该内容
}
- (void)runOperation {

    NSLog(@"%s", __func__);
}
- (IBAction)otherOperationBtnClick:(id)sender {
    [self performSelector:@selector(task2) onThread:self.thread withObject:nil waitUntilDone:YES];
}
- (void)task2 {
    NSLog(@"task2-----------%@", [NSThread currentThread]);
}

关注一下又不会怀孕.png
上一篇下一篇

猜你喜欢

热点阅读