iOS开发与应用OC语法iOS开发技巧

iOS多线程篇-RunLoop

2016-01-17  本文已影响653人  LitterL

RunLoop

简述

1、RunLoop是事件接收和分发机制的一个实现
2、并且它能处理App中的各种事件(比如触摸事件、定时器事件、Selector事件)
3、以及节省CPU资源,提高程序性能:(该做事时做事,该休息时休息)

如何获取Runloop对象:

这里的话IOS提供了两套API来访问或使用RunLoop
    1、CFRunLoopRef      是在 CoreFoundation 框架内的,它提供了纯 C 函数的 API,所有这些 API 都是线程安全的。
    2、NSRunLoop         是基于 CFRunLoopRef 的封装,提供了面向对象的 API,但是这些 API 不是线程安全的。

CFRunLoopRef的代码是开源的,你可以在这里CFRunLoopRef源码下载到整个 CoreFoundation 的源码

每一个线程对应着一个RunLoop,但是线程在创建的时候是没有RunLoop的,如果你不去获取它,它会一直没有,当然必须你自己的主动去获取,但是在你线程结束的时候,你所获取的RunLoop也跟着销毁了。如果你需要在某个线程对你自己的RunLoop执行一些事件的时候,那么你就的在线程未结束之前进行操作,然而在程序中是具有一个主RunLoop的,它用来管理程序的生死,具体的话是在UIApplicationMain里面执行

//具体显示
int main(int argc, char * argv[]) {
    @autoreleasepool {
        //程序开始执行  会输出这段语句
        NSLog(@"------------------");
        //可以看出这里面是一直执行的  相当于一个死循环
        int result = UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
        //程序结束了才会执行  会输出这段语句,在未结束之前这句话是不会执行的
        NSLog(@"++++++++++++++++++");
        return result;
    }
}

获取的方式

//获取的两种方式

1、这种为CFRunLoopRef中的
    CFRunLoopGetCurrent(); // 获得当前线程的RunLoop对象
    CFRunLoopGetMain(); // 获得主线程的RunLoop对象

2、这种为NSRunLoop中的
    [NSRunLoop currentRunLoop]; // 获得当前线程的RunLoop对象
    [NSRunLoop mainRunLoop]; // 获得主线程的RunLoop对象

相关类

//相关的五个类

1、CFRunLoopRef
    1、代表一个RunLoop对象
2、CFRunLoopModeRef
    1、代表RunLoop的运行模式
        1、一个RunLoop包含若干个Mode,每个Mode又包含若干个Source/Timer/Observer
        2、每次RunLoop启动时,只能指定其中一个 Mode,如果需要切换Mode,只能退出Loop,再重新指定一个Mode进入
        3、同一时刻只能进行一种模式
    2、苹果内部提供了五种模式
        1、kCFRunLoopDefaultMode (NSDefaultRunLoopMode)
            1、App的默认Mode,通常主线程是在这个Mode下运行
        2、UITrackingRunLoopMode
            1、界面跟踪 Mode,用于 ScrollView 追踪触摸滑动,保证界面滑动时不受其他 Mode 影响
        //这个通常用不到
        3、UIInitializationRunLoopMode
            1、在刚启动 App 时第进入的第一个 Mode,启动完成后就不再使用
        //这个通常用不到
        4、GSEventReceiveRunLoopMode
            1、接受系统事件的内部 Mode
        5、kCFRunLoopCommonModes
            1、这是一个占位用的Mode,这个的话用语言很难表达,后面会看到实例中会使用到这里,大家仔细体会
3、CFRunLoopSourceRef
    1、用来管理所有事件的事件源,包括自定义的事件,以及系统自带的事件。
    2、Source有两个版本:Source0 和 Source1
        1、Source0-----为用户主动触发的事件
        2、Source1-----通过内核和其他线程相互发送消息。
4、CFRunLoopTimerRef
    1、基本上说的就是NSTimer,基本用法如下实例标示
5、CFRunLoopObserverRef
    1、用来监听RunLoop的状态改变
    2、状态列表
        kCFRunLoopEntry         = (1UL << 0), // 即将进入Loop
        kCFRunLoopBeforeTimers  = (1UL << 1), // 即将处理 Timer
        kCFRunLoopBeforeSources = (1UL << 2), // 即将处理 Source
        kCFRunLoopBeforeWaiting = (1UL << 5), // 即将进入休眠
        kCFRunLoopAfterWaiting  = (1UL << 6), // 刚从休眠中唤醒
        kCFRunLoopExit          = (1UL << 7), // 即将退出Loop
        kCFRunLoopAllActivities = 0x0FFFFFFFU //所有状态

补充

一个RunLoop有很多Mode,一个Mode里面有很多得Source/Timer/Observer,但是同一时刻只能进行一种模式。 如图:

实例

// 在这里的话可以看到,我们滑动的时候它才会输出,因为我们forMode的为UITrackingRunLoopMode,
[[NSRunLoop currentRunLoop] addTimer:time forMode:UITrackingRunLoopMode];
看了上面两种是不是有种感觉为什么两者不能共存,那么下面这种就可以看到它们共存了objc
NSTimer *time = [NSTimer timerWithTimeInterval:1 target:self selector:@selector(show) userInfo:nil repeats:YES];
// 在这里的话可以看到,我们不管是程序启动还是滑动的时候它都会输出,因为我们forMode的为kCFRunLoopCommonModes,
[[NSRunLoop currentRunLoop] addTimer:time forMode:kCFRunLoopCommonModes];
```

上一篇下一篇

猜你喜欢

热点阅读