iOS 中NSRunLoop的使用


一、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://developer.apple.com/library/ios/#documentation/Cocoa/Conceptual/Multithreading/RunLoopManagement/RunLoopManagement.html

http://www.wim.me/nsurlconnection-in-its-own-thread/

http://xubenyang.me/384

http://iphonedevelopmentbits.com/event-driven-multitasking-runloopssymbian-ios


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM