博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
iOS运行回路(RunLoop)总结
阅读量:4071 次
发布时间:2019-05-25

本文共 2572 字,大约阅读时间需要 8 分钟。

原文:

首先看两个runloop的示例,来源:

第一个:

 
#include <CoreFoundation/CoreFoundation.h> 
 
static void 
_perform(void *info __unused) 
    printf("hello\n"); 
 
static void 
_timer(CFRunLoopTimerRef timer __unused, void *info) 
    CFRunLoopSourceSignal(info); 
 
int 
main() 
    CFRunLoopSourceRef source; 
    CFRunLoopSourceContext source_context; 
    CFRunLoopTimerRef timer; 
    CFRunLoopTimerContext timer_context; 
 
    bzero(&source_context, sizeof(source_context)); 
    source_context.perform = _perform; 
    source = CFRunLoopSourceCreate(NULL, 0, &source_context); 
    CFRunLoopAddSource(CFRunLoopGetCurrent(), source, kCFRunLoopCommonModes); 
 
    bzero(&timer_context, sizeof(timer_context)); 
    timer_context.info = source; 
    timer = CFRunLoopTimerCreate(NULL, CFAbsoluteTimeGetCurrent(), 1, 0, 0,
    _timer, &timer_context); 
    CFRunLoopAddTimer(CFRunLoopGetCurrent(), timer, kCFRunLoopCommonModes); 
 
    CFRunLoopRun(); 
 
    return 0; 
 

 

第二个:
 
#include <dispatch/dispatch.h> 
#include <stdio.h> 
 
int 
main() 
    dispatch_source_t source, timer; 
 
    source = dispatch_source_create(DISPATCH_SOURCE_TYPE_DATA_ADD, 0, 0,
    dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)); 
    dispatch_source_set_event_handler(source, ^{ 
        printf("hello\n"); 
    }); 
    dispatch_resume(source); 
 
    timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0,
    dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)); 
    dispatch_source_set_timer(timer, DISPATCH_TIME_NOW, 1ull * NSEC_PER_SEC, 0); 
    dispatch_source_set_event_handler(timer, ^{ 
        dispatch_source_merge_data(source, 1); 
    }); 
    dispatch_resume(timer); 
 
    dispatch_main(); 
 
功能是向main线程中加入两个input source,一个是timer,一个是自定义input source,然后这个timer中触发自定义source,于是调用其回调方法。 在这儿timer触发source来调用回调方法,显得有点多此一举。但是在多线程开发当中,这就很有用了,我们可以把这个自定义的source加入到子线程的runloop中,然后在主线程中触发source,这样在子线程中就可以调用回调方法了。  这样做的好久是什么呀? 节约用电,因为runloop一般情况下是休眠的,只有事件触发的时候才开始工作。 这与windows下的waitforsingleobject有点类似, 与多线程中的信号量,事件也有些雷同。
 
上面说到的input source(输入源例)到底是什么呢?输入源样例可能包括用户输入设备(如点击button)、网络链接(socket收到数据)、定期或时间延迟事件(NSTimer),还有异步回调(NSURLConnection的异步请求)。然后我们对其进行了分类,有三类可以被runloop监控,分别是sources、timers、observers。
在苹果文档中对runloop有详细介绍,下面参考中有中文版。那文档中的代码关于NSPort的部份在iOS上是不行的,不过可以用其CF方法实现,在我的demo中有展示。
 
每一个线程都有自己的runloop, 主线程是默认开启的,创建的子线程要手动开启,因为NSApplication 只启动main applicaiton thread。
没有source的runloop会自动结束。
事件由NSRunLoop 类处理。
RunLoop监视操作系统的输入源,如果没有事件数据, 不消耗任何CPU 资源。
如果有事件数据,run loop 就发送消息,通知各个对象。
用 currentRunLoop 获得 runloop的 reference
给 runloop 发送run 消息启动它。
 
 
文档中介绍下面四种情况是使用runloop的场合:
1.使用端口或自定义输入源和其他线程通信
2.子线程中使用了定时器
3.cocoa中使用任何performSelector到了线程中运行方法
4.使线程履行周期性任务,(我把这个理解与2相同)
如果我们在子线程中用了NSURLConnection异步请求,那也需要用到runloop,不然线程退出了,相应的delegate方法就不能触发。
解决的方法参看:
 
参考:

转载地址:http://dneji.baihongyu.com/

你可能感兴趣的文章
获取iOS版本号
查看>>
获取 一个文件 在沙盒Library/Caches/ 目录下的路径
查看>>
图片压缩
查看>>
检测缓存文件是否超时
查看>>
十进制字符串转十六进制字符串
查看>>
属性字符串(富文本)的使用
查看>>
cell上label的背景颜色在选中状态下改变的解决办法
查看>>
GPS定位
查看>>
地图、显示用户位置、大头针
查看>>
自定义大头针
查看>>
UIButton添加block点击事件
查看>>
利用runtime给类别添加属性
查看>>
iOS使用支付宝支付步骤
查看>>
本地推送
查看>>
远程推送
查看>>
访问系统相册
查看>>
FMDB的使用
查看>>
UIImage存为本地文件与UIImage转换为NSData
查看>>
通知的使用
查看>>
KVC与KVO
查看>>