设为首页 加入收藏

TOP

iOS开发 - RunLoop理解(二)
2017-10-12 11:01:26 】 浏览:10047
Tags:iOS 开发 RunLoop 理解
SDKeyRunLoopCntr)) { _CFSetTSD(__CFTSDKeyRunLoopCntr, (
void *)(PTHREAD_DESTRUCTOR_ITERATIONS-1), (void (*)(void *))__CFFinalizeRunLoop); } } return loop; }

RunLoop相关类

 Core Foundation中关于RunLoop的5个类

  • CFRunLoopRef
  • CFRunLoopModeRef
  • CFRunLoopSourceRef
  • CFRunLoopTimerRef (基于时间的触发器)
  • CFRunLoopObserverRef

说明:一个RunLoop包含若干个Mode,每个Mode又包含若干个Source、Timer、Observer,每次RunLoop启动时,只能指定一个Mode,这个Mode被称作CurrentMode,如果需要切换Mode,只能退出Loop,在重新指定一个Mode进入,这样做主要是为了分隔开不同组的 Source/Timer/Observer,让其互不影响。

1.CFRunLoopSourceRef :事件源(输入源)

     - Source0:非基于Port的 (用户主动触发的事件)

     - Source1:基于Port的 (系统内部的消息事件)

(Port是线程间通信的一种方式,如果两个线程之间想通信,可以通过Port来通信。)

 

2.CFRunLoopTimerRef

基于时间触发器,当其加入RunLoop时,RunLoop会注册对应的时间点,当时间点到,RunLoop会被唤醒执行里面的回调。

 

3.CFRunLoopObserverRef 

观察者,能够监听RunLoop的状态改变。

/* Run Loop Observer Activities */

typedef CF_OPTIONS(CFOptionFlags, CFRunLoopActivity) {

kCFRunLoopEntry = (1UL << 0),//即将进入Loop

kCFRunLoopBeforeTimers = (1UL << 1),//即将处理Timer

kCFRunLoopBeforeSources = (1UL << 2),//即将处理Source

kCFRunLoopBeforeWaiting = (1UL << 5),//即将进入休眠

kCFRunLoopAfterWaiting = (1UL << 6),//刚从休眠中唤醒

kCFRunLoopExit = (1UL << 7),//即将退出Loop

kCFRunLoopAllActivities = 0x0FFFFFFFU

};

 

-(void)addObserver{
    
    /*
     参数一:怎么分配存储空间
     参数二:要监听的状态 kCFRunLoopAllActivities 所有的状态
     参数三:是否要持续监听
     参数四:优先级,总是传0
     参数五:当状态改变时候的回调
     */
    
    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(@"即将处理Sources事件");
                break;
            case kCFRunLoopBeforeWaiting:
                NSLog(@"即将进入睡眠");
                break;
            case kCFRunLoopAfterWaiting:
                NSLog(@"被唤醒");
                break;
            case kCFRunLoopExit:
                NSLog(@"runloop退出");
                break;
                
            default:
                break;
        }
        
    });
    //给runloop添加监听者
    /*
     参数一:要监听哪个runloop
     参数二:观察者
     参数三:运行模式
     */
    CFRunLoopAddObserver(CFRunLoopGetCurrent(), observer, kCFRunLoopDefaultMode);
}

 

4.CFRunLoopModeRef :RunLoop的运行模式

在RunLoop中有多个运行模式,但是RunLoop只能选择一种模式运行,Mode里面至少要有Timer或者Source

系统默认注册了5个Mode:

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

RunLoop相关问题及解释 

1.Timer与滑动控件的问题

问题:当在不停地拖动滑动控件的时候,定时器不工作了

错误回答:runloop的优先级

分析:runloop的几种常用模式:DefaultMode默认模式,以及UITrackingMode模式,CommonModes占位模式,runloop进入一种模式的时候,另一种模式的事件不会去处理,当Timer在运行的时候处于DefaultMode模式,当拖动滑动控件的时候,runloop会立即处理UI事件,切换到UITrackingRunLoopMode模式后,此时DefaultMode模式下的Timer就不工作了

解决:将Timer置于NSRunLoopCommonModes占位模式下

- (void)viewDidLoad {

    [super viewDidLoad];

    //1.创建定时器

    NSTimer *timer = [NSTimer timerWithTimeInterval:2.0 target:self selector:@selector(run) userInfo:nil repeats:YES];

    
    //2.将Timer添加到RunLoop中

    //[[NSRunLoop currentRunLoop]addTi
首页 上一页 1 2 3 下一页 尾页 2/3/3
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇iOS ----------怎么修改xcode默认.. 下一篇iPhone与iWatch连接、控制、数据..

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目