美文网首页
ios- runloop

ios- runloop

作者: child_cool | 来源:发表于2017-04-23 14:14 被阅读6次
/**
 @param argc 参数长度
 @param argv 参数值
 */
int main(int argc, char * argv[]) {
}
/*
 runloop - 运行循环
 1.保证程序不退出,也就是建立死循环
 2.负责监听事件(网络事件,时钟事件,触摸事件)
 3.如果没有事件发生,runloop进入休眠状态
4.渲染图片,在一次循环中渲染所有的图片
 
 每一条线程上都会有一个runloop。但是默认不开启,想让线程不被释放,需要将该线程的runloop运行起来
 屏幕每秒钟闪烁60次
 
 模式:
 默认模式-NSDefaultRunLoopMode 
 ui处理模式-UITrackingRunLoopMode(优先级高)(只能被ui事件触发)  
 占位模式 - NSRunLoopCommonModes  可以解决时钟事件和ui处理事件的冲突(有隐患)
 模式上的事件:source timer observe
 /*
 source  : 事件源  
        source0:非内核事件
        source1:系统内核事件
 observe : 观察者
 timer : 时钟
 */
 如果在时钟监听事件中执行耗时操作(线程睡眠,)会导致主线程被阻塞
 线程归属cpu进行调度
 */
解决方案一:
使用占位模式解决事件冲突问题(如果在时钟监听事件中执行耗时操作(线程睡眠,)会导致主线程被阻塞)
- (void)viewDidLoad {
    [super viewDidLoad];

    
   NSTimer *timer = [NSTimer timerWithTimeInterval:1.f target:self selector:@selector(timerMethod) userInfo:nil repeats:YES];
     [[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];// 添加到占位模式中
    
}

- (void)timerMethod {
    static int num = 0;
    num ++;
    NSLog(@"%@,%d",[NSThread currentThread],num);
}

解决方案二:
对方案隐患的问题解决和优化
在子线程中执行时钟会出现子线程开辟使用结束会自动释放,使用开启子线程runloop的模式解决该问题,在需要时在对子线程进行关闭或者停止runloop的运行循环
// 1.以关闭子线程runloop的方式解决
- (void)viewDidLoad {
    [super viewDidLoad];
    NSThread *thread = [[NSThread alloc] initWithBlock:^{
        NSTimer *timer = [NSTimer timerWithTimeInterval:1.f target:self selector:@selector(timerMethod) userInfo:nil repeats:YES];
        [[NSRunLoop currentRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode];// 添加到占位模式中
//        [[NSRunLoop currentRunLoop] run]; // 开启子线程runloop循环
        
        while (!self.isFanished) {
            // 每次RunLoop运行的时间
            [[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.001]];
        }
    }];
    
    [thread start];
    
}

- (void)timerMethod {
    [NSThread sleepForTimeInterval:1.f]; // 模拟主线程阻塞
    static int num = 0;
    num ++;
    NSLog(@"%@,%d",[NSThread currentThread],num);
}

// 2.以杀掉子线程的方式解决
- (void)viewDidLoad {
    [super viewDidLoad];
    NSThread *thread = [[NSThread alloc] initWithBlock:^{
        NSTimer *timer = [NSTimer timerWithTimeInterval:1.f target:self selector:@selector(timerMethod) userInfo:nil repeats:YES];
        [[NSRunLoop currentRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode];// 添加到占位模式中
        [[NSRunLoop currentRunLoop] run]; // 开启子线程runloop循环
    }];
    
    [thread start];
    
}

- (void)timerMethod {
    
    if (self.isFanished) {
        [NSThread exit]; // 杀掉当前线程
    }
    
    [NSThread sleepForTimeInterval:1.f]; // 模拟主线程阻塞
    static int num = 0;
    num ++;
    NSLog(@"%@,%d",[NSThread currentThread],num);
}

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
    self.isFanished = YES;
}

小知识:
 [NSThread exit]; // 杀掉当前线程
可以通过该方法杀掉主线程,程序不会崩溃,但ui不会再进行处理
解决方案三:
使用gcd 不需要去额外处理runloop的问题
  /**
     全局队列

     @param 0 优先级
     @param 0 预留参数
     */
    dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
    
    
    /**
     创建定时器

     @param DISPATCH_SOURCE_TYPE_TIMER 定时器类型
     @param queue 全局队列可以进行异步处理
     */
    dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);
    
    /**
     DISPATCH_TIME_NOW 启动时间
     1 * NSEC_PER_SEC = 1000,000,000 间隔时间 1秒
     */
    dispatch_source_set_timer(timer, DISPATCH_TIME_NOW, 1 * NSEC_PER_SEC, 0 * NSEC_PER_SEC);
    dispatch_source_set_event_handler(timer, ^{
        NSLog(@"%@",[NSThread currentThread]);
    });
    // 启动定时器
    dispatch_resume(timer);
在TableViewcell中添加多张高清大图,一次性加载多个时会出现卡顿现象,示例如下:https://github.com/feng562925462/iOSRunloop-

相关文章

网友评论

      本文标题:ios- runloop

      本文链接:https://www.haomeiwen.com/subject/jwoezttx.html