转载

iOS-RunLoop

RunLoop总结

需要思考问题

为什么程序在使用的时候可以接受用户的触摸事件,不使用的时候什么事件都不发生?

查看一下 main.m 文件,这是程序启动的入口函数。

int main(int argc, char * argv[]) {
@autoreleasepool {
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
}
}

代码调用的时候,主线程也开始运行。文档上说 UIApplicationMain 函数指定了appliacaion的delegate,并且开启了event cycle。那什么是event cycle?

RunLoop

程序的event cycle其实就是RunLoop,RunLoop在程序启动的时候就开启,接受用户的处理事件。

这是官方文档上面的一个图,可以看到RunLoop在线程中循环监听需要处理的事件。能够接收两种不同的事件源

  • Input sources(输入源):传递异步事件。
  • Timer sources(定时器): 传递同步事件、发生在特定时间或者重复的时间间隔。

iOS-RunLoop

RunLoop Mode

  • Default模式:几乎包含了所有输入源,一般情况下使用这个模式

    • NSDefaultRunLoopMode (Cocoa)
    • kCFRunLoopDefaultMode (Core Foundation)
  • Connection模式

    • 处理NSConnection对象相关事件,系统内部使用,用户基本不会使用。
  • Modal模式
    • 处理modal panels事件
  • Event tracking模式:滑动Scrollview、Tableview的时候就处于这个模式

    • UITrackingRunLoopMode(iOS)
    • NSEventTrackingRunLoopMode(cocoa)
  • Common模式: 模式的组合,所有的模式下都可以处理

    • NSRunLoopCommonModes (Cocoa)
    • kCFRunLoopCommonModes (Core Foundation)

RunLoop与线程的关系

每条线程都有唯一的RunLoop对象与之对应,主线程的RunLoop是自动创建并启动的。子线程的RunLoop需要手动创建,并且调用 run 方法启动。 currentRunLoop 是延迟加载的,只创建一次.

[[NSRunLoop currentRunLoop] run];

指定RunLoop运行的模式和过期时间

- (BOOL)runMode:(NSString *)mode beforeDate:(NSDate *)limitDate;

使用场景

1、NSTimer

如果在ScrollView里面使用到NSTimer的,需要调用 addTimer:forMode 方法指定model,才能在滚动的时候生效。

NSTimer创建的定时器因为需要指定model运行,在RunLoop中需要处理各种事件,导致NSTimer不精确。可以使用GCD方法来创建,GCD不受RunLoop的Mode影响.

 dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);


dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);
// 要搞一个强引用,不然定时器创建出来就挂了
self.timer = timer;

// 延迟3秒开始执行
dispatch_time_t start = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3.0 * NSEC_PER_SEC));
// 每隔2秒执行一次
uint64_t interval = (uint64_t)(2.0 * NSEC_PER_SEC);
dispatch_source_set_timer(self.timer, start, interval, 0);

// 要执行的任务
dispatch_source_set_event_handler(self.timer, ^{
NSLog(@"%s",__func__);
});

// 启动定时器
dispatch_resume(self.timer);

// 停止定时器
dispatch_cancel(self.timer);

2、ImageView的加载

图片的加载放在 NSDefaultRunLoopMode ,因为ScrollView的滚动是在 UITrackingRunLoopMode 下运行的。

3、PerformSelector指定执行的模式

- (void)performSelector:(SEL)aSelector withObject:(nullable id)anArgument afterDelay:(NSTimeInterval)delay inModes:(NSArray<NSString *> *)modes;

参考

1、 官方文档

2、 http://www.cnblogs.com/xuebao/p/4643704.html

正文到此结束
Loading...