美文网首页
iOS底层day8 - RunLoop

iOS底层day8 - RunLoop

作者: 宁夏灼雪__ | 来源:发表于2018-10-31 17:17 被阅读0次

    什么是RunLoop

    运行循环,可以在程序运行中做一些事情(处理source、timer、observer),一个线程对应一个RunLoop,主线程默认开启RunLoop,子线程需要手动触发,我们一个iOS应用就是启动了RunLoop一直在循环(UIApplicationMain),所以程序才没有退出。

    RunLoop应用

    • 定时器(timer)、PerfromSelector
    • GCD Async main queue
    • 事件响应、手势识别、界面刷新
    • 网络请求
    • AutoReleasePool
      …………

    RunLoop的基本作用

    • 保持程序持续运行
    • 处理App的各种事件(触摸、定时器)
    • 节省cpu资源、提高程序性能,该做事的时候做事,该休息的时候休息

    RunLoop结构

    我们先看图:


    runloop结构

    每个RunLoop里面会保留一个_pthread线程对象,一个RunLoop对应一个_pthread_currentMode为当前RunLoop的时运行模式,一个模式包含了_source0_source1_observers_timers,一个RunLoop同一个时间点只能运行一个模式currentMode

    RunLoop运行逻辑

    RunLoop运行逻辑

    大致了解一下,RunLoop里面在循环处理Blocks、Timer、Source、Observer、GCD等操作,处理结束会进入休眠,唤醒又会继续处理操作

    RunLoop在开发中的应用

    • 控制线程声明周期 (线程保活)
    • 处理NSTimer在滑时停止工作
    • 监听应用卡顿
    • 性能优化

    处理NSTimer在滑时停止工作

    因为RunLoop从静止状态切换到滑动状态的时候是切换Mode的,从NSDefaultRunLoopMode切换到UITrackingRunLoopMode,而定时器的处理是在NSDefaultRunLoopMode中,所以这里的解决方案是把定时器加入到NSRunLoopCommonModes

    控制线程声明周期 (线程保活)

    一个线程执行完他的事情后,线程就会销毁,而我们开发中有时候需要一个常驻线程,用于处理一些耗时的操作,而我们一直创建线程、销毁线程是比较消耗性能的一件事, 所以,我们必须在程序运行中保护好该线程,这里就需要使用到RunLoop
    例子如下:

    #import "ViewController.h"
    #import "MJThread.h"
    @interface ViewController ()
    @property (nonatomic,assign)BOOL isStop;
    @property (nonatomic,strong)MJThread *thread;
    @end
    
    @implementation ViewController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        __weak typeof(self)weakSelf = self;
        self.isStop = NO;
        self.thread = [[MJThread alloc] initWithBlock:^{
            NSLog(@"---begin---");
            [[NSRunLoop currentRunLoop] addPort:[[NSPort alloc] init] forMode:NSDefaultRunLoopMode];
            while (weakSelf && !weakSelf.isStop) {
                [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
            }
            NSLog(@"---end---");
        }];
        [self.thread start];
        
    }
    
    - (IBAction)stop {
        if (!self.thread) return;
        [self performSelector:@selector(stopAction) onThread:self.thread withObject:nil waitUntilDone:YES];
    }
    
    - (void)stopAction {
        
        self.isStop = YES;
        CFRunLoopStop(CFRunLoopGetCurrent());
        self.thread = nil;
    }
    
    - (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
    {
        // 执行
        if (!self.thread) return;
        [self performSelector:@selector(run) onThread:self.thread withObject:nil waitUntilDone:YES];
    }
    
    - (void)run {
        NSLog(@"------%s----%@---",__func__,[NSThread currentThread]);
    }
    
    
    @end
    

    这里,我们启动一个线程,在线程中获取RunLoop,因为子线程的RunLoop默认是没有东西的,如果不往RunLoop里面添加东西的话,它就会了立刻结束,所以我们在这里添加一个NSPort对象,接下来我们进入一个While循环执行runMode,在我理解里,runMode方法类似RunLoop的一次循环,这里进入了休眠,而我们加入一个while循环,就可以实现我们手动控制它循环,只有当我们手动把标记换掉后,停止RunLoop,循环才会结束,线程就会销毁

    相关文章

      网友评论

          本文标题:iOS底层day8 - RunLoop

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