美文网首页
iOS RunLoop笔记

iOS RunLoop笔记

作者: 梦醒了i77 | 来源:发表于2019-02-22 15:05 被阅读0次

RunLoop

  • RunLoop内部实现就是do-while循环,在这循环之内不断地处理各种任务(Source、Timer、Observer)
  • 一个线程对应一个RunLoop,主线程的RunLoop默认已启动,子线程RunLoop得手动创建并调用run方法
  • RunLoop只能选择一个Mode启动,如果当前Mode中没有Sourcr、Timer,那么就直接退出RunLoop

RunLoop运行流程

  1. 通知Observer:即将进入Loop
  2. 通知Observer:将要处理Timer
  3. 通知Observer:将要处理Source0
  4. 处理Source0
  5. 如果有Source1,跳到第九步
  6. 通知Observer:线程即将休眠
  7. 休眠,等待唤醒
  8. 通知Observer:线程刚被唤醒
  9. 处理唤醒时收到的消息,之后跳回2
  10. 通知Observer:即将退出Loop

CFRunLoopModeRef

  • kCFRunLoopDefaultMode
    • App的默认Mode,通常主线程是在这个Mode下运行
  • UITrackingRunLoopMode
    • 界面跟踪Mode,用于ScrollView追踪触摸滑动,保证界面滑动时不受其他Mode影响
  • UIInitializationRunLoopMode
    • 在刚启动App时进入的第一个Mode,启动完成后就不再使用
  • GSEventReceiveRunLoopMode
    • 接收系统事件的内部Mode
  • kCFRunLoopCommonModes
    • 这是一个占位用的Mode,不是一种真正的Mode

CFRunLoopSourceRef

  • Source0:非基于Port
  • Source1:基于Port

CFRunLoopObserverRef

  • 监听RunLoop状态
CFRunLoopObserverRef observer = CFRunLoopObserverCreateWithHandler(CFAllocatorGetDefault(), kCFRunLoopAllActivities, YES, 0, ^(CFRunLoopObserverRef observer, CFRunLoopActivity activity) {
          switch (activity) {
               case kCFRunLoopEntry:
                    NSLog(@"即将进入RunLoop");
                    break;
               case kCFRunLoopBeforeTimers:
                    NSLog(@"即将处理Timer事件");
                    break;
               case kCFRunLoopBeforeSources:
                    NSLog(@"即将处理TSources事件");
                    break;
               case kCFRunLoopBeforeWaiting:
                    NSLog(@"即将进入休眠");
                    break;
               case kCFRunLoopAfterWaiting:
                    NSLog(@"RunLoop被唤醒");
                    break;
               case kCFRunLoopExit:
                    NSLog(@"RunLoop退出");
                    break;
               default:
                    break;
          }
     });
     
CFRunLoopAddObserver(CFRunLoopGetCurrent(), observer, kCFRunLoopDefaultMode);

常驻子线程

  • 开启一个子线程
  • 创建子线程的RunLoop,并设置RunLoop一个Source或者Timer,否则RunLoop创建即退出
  • 开启RunLoop run
#import "ViewController.h"

@interface ViewController ()

@property(nonatomic, strong)NSThread *thread;

@end

@implementation ViewController

- (void)viewDidLoad {
     [super viewDidLoad];
     // Do any additional setup after loading the view, typically from a nib.
}

- (IBAction)createThread {
     
     self.thread = [[NSThread alloc] initWithTarget:self selector:@selector(create) object:nil];
    
     [self.thread start];
}

- (void)create{
     
     NSLog(@"%s", __func__);
     
     NSRunLoop *runLoop = [NSRunLoop currentRunLoop];
     
     [runLoop addPort:[NSPort port] forMode:NSDefaultRunLoopMode];
     
     [runLoop run];
}

- (IBAction)executeTask:(id)sender {
     [self performSelector:@selector(task) onThread:self.thread withObject:nil waitUntilDone:YES];
}

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

@end

关于自动释放池

  • 第一次创建:启动RunLoop
  • 最后一次销毁:RunLoop退出的时候
  • 其他时候的创建和销毁:当RunLoop即将睡眠的时候销毁之前的释放池,重新创建一个新的

相关文章

网友评论

      本文标题:iOS RunLoop笔记

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