一、RunLoop的使用示例
1、
#import <UIKit/UIKit.h>
#import <CoreFoundation/CoreFoundation.h>
#import "AppDelegate.h"
static void _perform(void *info __unused)
{
printf("hello\n");
}
static void _timer(CFRunLoopTimerRef timer __unused, void *info)
{
CFRunLoopSourceSignal(info);
}
int main(int argc, char *argv[])
{
@autoreleasepool {
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();
returnUIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegateclass]));
}
}
2、
#import <UIKit/UIKit.h>
#import <stdio.h>
#import "AppDelegate.h"
int main(int argc, char *argv[])
{
@autoreleasepool {
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, ^{
printf("world\n");
dispatch_source_merge_data(source, 1);
});
dispatch_resume(timer);
dispatch_main();
returnUIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegateclass]));
}
}
两个示例的功能是:
在主线程中加入两个input source, 一个是timer ,另一个是自定义input source .
在timer中触发自定制的input source;然后在input source 中触发timer.相互回调。
在多线程的开发中,把这个自定义的source加入到子线程的runloop中,然后在主线程中触发source,
runloop一般情况下是休眠的,只有事件触发的时候才开始工作。节省资源。
input source(输入源):输入源可以是用户输入设备(如点击button)、网络链接(socket收到数据)、
定期或时间延迟事件(NSTimer),还有异步回调(NSURLConnection的异步请求)。
然后我们对其进行了分类,有三类可以被runloop监控,分别是sources、timers、observers。
每一个线程都有自己的runloop, 主线程是默认开启的,创建的子线程要手动开启,因为NSApplication 只启动main applicaiton thread。
没有source的runloop会自动结束。
事件由NSRunLoop 类处理。
RunLoop监视操作系统的输入源,如果没有事件数据, 不消耗任何CPU 资源。
如果有事件数据,run loop 就发送消息,通知各个对象。
用 currentRunLoop 获得 runloop的 reference
给 runloop 发送run 消息启动它。
使用runloop的四种场合:
1.使用端口或自定义输入源和其他线程通信
2.子线程中使用了定时器
3.cocoa中使用任何performSelector到了线程中运行方法
4.使线程履行周期性任务
如果我们在子线程中用了NSURLConnection异步请求,那也需要用到runloop,不然线程退出了,相应的delegate方法就不能触发。
解决的方法参看:
http://www.cocoabyss.com/foundation/nsurlconnection-synchronous-asynchronous/
http://www.wim.me/nsurlconnection-in-its-own-thread/
参考:
http://www.wim.me/nsurlconnection-in-its-own-thread/
http://iphonedevelopmentbits.com/event-driven-multitasking-runloopssymbian-ios