一、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