19 RunLoop的应用

作者: zysmoon | 来源:发表于2020-01-20 14:42 被阅读0次
    RunLoop在实际开中的应用
    • 控制线程生命周期(线程保活)
    • 解决NSTimer在滑动时停止工作的问题
    • 监控应用卡顿
    • 性能优化
    一 解决NSTimer在滑动时停止工作的问题
    • 在拖拽时定时器不工作
    __block int count = 0;
    
    // 默认添加到default模式
    [NSTimer scheduledTimerWithTimeInterval:1.0 repeats:YES block:^(NSTimer * _Nonnull timer) {
        NSLog(@"%d", ++count);
    }];
    
    

    打印结果

    1653926-cb07f0ee4f690f8b.png
    • 在拖拽时人仍然正常工作
    static int count = 0;
    // 2.添加到指定模式下
    NSTimer *timer = [NSTimer timerWithTimeInterval:1.0 repeats:YES block:^(NSTimer * _Nonnull timer) {
        NSLog(@"%d", ++count);
    }];
    //    [[NSRunLoop currentRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode];
    //    [[NSRunLoop currentRunLoop] addTimer:timer forMode:UITrackingRunLoopMode];
    
    // NSDefaultRunLoopMode、UITrackingRunLoopMode才是真正存在的模式
    // NSRunLoopCommonModes并不是一个真的模式,它只是一个标记
    // timer能在_commonModes数组中存放的模式下工作
    [[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];
    
    
    1653926-33d7a778a1279794.png
    二 线程保活

    我们先封装一个长久活命的线程

    • PermanentThread.h
    // 声明一个block - 用于执行任务
    typedef void(^PermanentThreadTask)(void);
    
    /** 线程保活 */
    @interface PermanentThread : NSObject
    
    // 在当前线程执行一个任务
    - (void)executeTask:(PermanentThreadTask)task;
    
    // 结束线程
    - (void)stop;
    
    @end
    
    
    • PermanentThread.m
    /** CSThread **/
    @interface CSThread : NSThread
    @end
    @implementation CSThread
    - (void)dealloc {
        NSLog(@"%s", __func__);
    }
    @end
    
    @interface PermanentThread()
    /** 线程*/
    @property(nonatomic,strong)CSThread *thread;
    /** 是否停止*/
    @property(nonatomic,assign, getter=isStopped)BOOL stopped;
    @end
    
    @implementation PermanentThread
    
    // 初始化方法
    - (instancetype)init {
        self = [super init];
        if (self) {
            self.stopped = NO;
    
            // 初始化线程
            __weak typeof(self) weakSelf = self;
            self.thread = [[CSThread alloc] initWithBlock:^{
                // runloop只有添加事件才会执行
                [[NSRunLoop currentRunLoop] addPort:[[NSPort alloc]init] forMode:NSDefaultRunLoopMode];
    
                // 当当前对象存在并且变量为false的时候,才一直执行
                while (weakSelf && !weakSelf.isStopped) {
                    [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
                }
            }];
    
            // 开启线程
            [self.thread start];
        }
        return self;
    }
    
    - (void)dealloc {
        NSLog(@"%s", __func__);
    
        [self stop];
    }
    
    #pragma mark - public method
    
    // 执行任务
    - (void)executeTask:(PermanentThreadTask)task {
        // 如果线程释放或者无任务,则退出
        if (!self.thread || !task) {
            return;
        }
    
        // 开始执行任务
        [self performSelector:@selector(innerExecuteTask:) onThread:self.thread withObject:task waitUntilDone:NO];
    }
    
    // 停止
    - (void)stop {
        if (!self.thread) {
            return;
        }
    
        [self performSelector:@selector(innerStop) onThread:self.thread withObject:nil waitUntilDone:YES];
    }
    
    #pragma mark - private method
    
    // 执行任务
    - (void)innerExecuteTask:(PermanentThreadTask)task {
        task();
    }
    
    // 停止线程 runloop
    - (void)innerStop {
        self.stopped = YES;
        CFRunLoopStop(CFRunLoopGetCurrent());
        self.thread = nil;
    }
    
    @end
    
    

    外部调用

    - (void)viewDidLoad {
        [super viewDidLoad];
    
        // 2.线程保活
        self.thread = [[PermanentThread alloc] init];
    }
    
    - (void)dealloc {
        NSLog(@"%s", __func__);
    }
    
    - (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
        [self.thread executeTask:^{
            NSLog(@"执行任务 - %@", [NSThread currentThread]);
        }];
    }
    
    - (void)stopBtnClick {
        [self.thread stop];
    }
    
    

    运行结果

    1653926-8ca5610aa7da3861.png

    本文参考:
    路飞_Luck (https://www.jianshu.com/p/07f7b96bb03f)
    以及借鉴MJ的教程视频
    非常感谢.


    项目连接地址 - RunLoop-应用

    相关文章

      网友评论

        本文标题:19 RunLoop的应用

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