• runloop


    runloop

    作用

    • 使程序一直运行并接收用户的输入
    • 决定程序在何时处理哪些事件
    • 调用解耦(Message Queue)
    • 节省CPU时间(当程序启动后,什么都没有执行的话,就不用让CPU来消耗资源来执行,直接进入睡眠状态)

    模式

    • RunLoop 在同一段时间只能且必须在一种特定的模式下运行
    • 如果要更换 Mode,必须先停止当前的 Loop,然后再重新启动 Loop
    • Mode 是保证滚动流畅的关键

    • NSDefaultRunLoopMode:默认状态、空闲状态

    • UITrackingRunLoopMode:滚动模式
    • UIInitializationRunLoopMode:私有的,App启动时
    • NSRunLoopCommonModes:默认包含1,2两种模式

    模拟 RunLoop 实现

    #import <objc/message.h>
    
    Person *person;
    
    void callFunc(int type) {
        NSLog(@"正在执行 %d...%@", type, person);
    
        UInt32 result = ((UInt32 (*)(id, SEL, int, NSString *))objc_msgSend)(person, @selector(hahaha:name:), type, @"zhangsan");
        NSLog(@"耗时 %u 秒", result);
    }
    
    int main(int argc, const char * argv[]) {
        @autoreleasepool {
            int result = 0;
            person = [[Person alloc] init];
    
            while (YES) {
                printf("请输入选择项,0表示退出:");
                scanf("%d", &result);
    
                if (result == 0) {
                    printf("88
    ");
                    break;
                } else {
                    callFunc(result);
                }
            }
        }
        return 0;
    }

    运行循环与时钟

    @interface ViewController ()
    @property (nonatomic, strong) NSTimer *timer;
    @end
    
    @implementation ViewController
    
    - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
        NSTimer *timer = [NSTimer timerWithTimeInterval:1.0 target:self selector:@selector(fire) userInfo:nil repeats:YES];
        [[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];
    }
    
    - (void)fire {
        static int num = 0;
    
        ///  耗时操作
        for (int i = 0; i < 1000 * 1000; ++i) {
            [NSString stringWithFormat:@"hello - %d", i];
        }
    
        NSLog(@"%d", num++);
    }
    
    @end

    运行测试,会发现卡顿非常严重

    • 将时钟添加到其他线程工作
    - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
        self.thread = [[NSThread alloc] initWithTarget:self selector:@selector(startTimer) object:nil];
        [self.thread start];
    }
    
    - (void)startTimer {
        @autoreleasepool {
            NSTimer *timer = [NSTimer timerWithTimeInterval:1.0 target:self selector:@selector(fire) userInfo:nil repeats:YES];
    
            [[NSRunLoop currentRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode];
    
            _timerRf = CFRunLoopGetCurrent();
            CFRunLoopRun();
    
            NSLog(@"come here");
        }
    }

    注意:主线程的运行循环是默认启动的,但是子线程的运行循环是默认不工作的,这样能够保证线程执行完毕后,自动被销毁

    • 停止运行循环
    - (IBAction)stop {
        if (_timerRf == NULL) {
            return;
        }
    
        CFRunLoopStop(_timerRf);
        _timerRf = NULL;
    }
  • 相关阅读:
    关于同时上传多个图片的类(有点粗糙)
    关于上传图片的类(有点粗糙)
    关于分页的类(有点粗糙)
    php是什么
    关于glod方法的使用和介绍
    PHP中从数据库获取查询结果时容易出的错误及原因(smarty)
    转载- 支持Android4.0以下webp的使用
    Android用户体验
    转载-Android数据库高手秘籍(一)——SQLite命令
    转载 -安卓开发-Activity中finish() onDestroy() 和System.exit()的区别
  • 原文地址:https://www.cnblogs.com/jiahao89/p/5118270.html
Copyright © 2020-2023  润新知