RunLoop

2018-01-30  本文已影响12人  spades_K

含义:运行循环 偏底层

原理: iOS在 UIApplicationMain()中开启,

目的:
1.保证程序不退出。

  1. 监听事件 触摸、时钟、网络事件。(所有事件跟硬件有关 响应式)

  2. 如果没有事件发生,让程序进入休眠状态。

//
//  ViewController.m
//  RunLoop
//
//  Created by john on 2018/1/30.
//  Copyright © 2018年 john. All rights reserved.
//

#import "ViewController.h"

@interface ViewController ()
{
    dispatch_source_t timer;
}
@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    
}

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

}



- (void)demo1
{
    /*
     // 封装下面两个  默认模式
     [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(timeActiom) userInfo:nil repeats:YES];
     */
    
    NSTimer *timer = [NSTimer timerWithTimeInterval:1.0 target:self selector:@selector(timeActiom) userInfo:nil repeats:YES];
    
    // 默认模式 当视图进行拖动时,事件不被调用
    [[NSRunLoop mainRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode];
    
    //  UI模式只在触摸事件才触发
    [[NSRunLoop mainRunLoop] addTimer:timer forMode:UITrackingRunLoopMode];
    
    //  占位模式 等于前两个之和的效果
    [[NSRunLoop mainRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];
    
    
    
    // timer事件会在UI拖拽过程中是不会执行的
    
    
    // runLoop模式
    /*
     1 默认模式   Source  Observe Timer  当视图进行拖动时,事件不被调用
     2 UI模式    Source  Observe Timer   优先级最高  只能被触摸事件所触发
     3 占位模式  NSRunLoopCommonModes
     */
}

- (void)demo2
{
    // 子线程
    NSThread *thread = [[NSThread alloc] initWithBlock:^{
        
        NSTimer *timer = [NSTimer timerWithTimeInterval:1.0 target:self selector:@selector(timeActiom) userInfo:nil repeats:YES];
        
        [[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];
        
        // 让runLoop跑起来  死循环  不会再执行下面代码
        // currentRunLoop 会调用CFRunloop() 第一次获取runLoop的时候创建RunLoop 懒加载
        [[NSRunLoop currentRunLoop] run]; // 跑起来停不了
        
        NSLog(@"来了"); //  runLoop没跑起来  对于事件 这个可以打印
        
        
        // 线程的生命要想保存  只能让它有执行不完的任务。
        //        while (true) {
        //        }
        
        
    }];
    
    [thread start];

}


- (void)demo3
{
    
    NSThread *thred = [[NSThread alloc] initWithBlock:^{
        
        NSLog(@"%@",[NSThread currentThread]);
    }];
    
    
    [thred start];
    
    // 线程通讯
    [self performSelector:@selector(otherMethod) onThread:thred withObject:nil waitUntilDone:NO];  // 这个 otherMethod方法不会走的 因为线程已经挂掉了  需要线程保活   事件中的通讯是runloop处理的

}

- (void)demo4
{
    // GCD实现
    //1 创建 timer
    timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, dispatch_get_global_queue(0, 0));
    // 设置 timer 1 秒一次
    dispatch_source_set_timer(timer, DISPATCH_TIME_NOW, 1.0 * NSEC_PER_SEC, 0);
    
    // 设置回调
    dispatch_source_set_event_handler(timer, ^{
        NSLog(@"%@",[NSThread currentThread]);
    });
    
    // 启动
    dispatch_resume(timer);
    
    
    /*
     Runloop中的source
     底层为 CFRunLoopSourceRef
     
     按照函数调用栈分类:
     Source0 : 不是Source1的就是Source0
     Source1: 内核和其他线程通讯事件。
     
     */
    

}
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
    // 杀掉主线程  程序整体无反应  但是子线程中runLoop还在跑
    /*
     UI是在主线程上面的
     app启动的第一条线程
     why 苹果这样设计  ?
     A: 安全加效率   UIKIT框架是线程不安全的框架  多线程会出现资源抢夺的情况 安全的话可以加线程锁 但是会出现效率低下的情况  所以苹果这么限制
     
     
     */
    [NSThread exit];
    
}


- (void)timeActiom
{
    NSLog(@"come l "); // 子线程中runloop不会走这个方法  因为此时线程已经被释放  如果用成员变量对这个线程持有,线程还是会被释放,持有的只是这个对象而已。
    // 耗时操作
//    [NSThread sleepForTimeInterval:1];
    NSLog(@"%@",[NSThread currentThread]);
}


- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}


@end
参考AF线程保活的方法
+ (void)networkRequestThreadEntryPoint:(id)__unused object {
    @autoreleasepool {
        [[NSThread currentThread] setName:@"AFNetworking"];

        NSRunLoop *runLoop = [NSRunLoop currentRunLoop];
        [runLoop addPort:[NSMachPort port] forMode:NSDefaultRunLoopMode];
        [runLoop run];
    }
}
上一篇下一篇

猜你喜欢

热点阅读