CFRunLoop 學習 例子,控制 runloop 時間
阿新 • • 發佈:2019-01-25
#import "ViewController.h" @interface ViewController () @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view, typically from a nib. //這裡偷個懶,直接使用performSelectorInBackground來建立一個執行緒,並執行configRunLoop方法 [self performSelectorInBackground:@selector(configRunLoop) withObject:nil]; UIButton* __button1 = [UIButton buttonWithType:UIButtonTypeRoundedRect]; [__button1 setTitle:@"Fire Event" forState:UIControlStateNormal]; //觸發事件啟動RunLoop [__button1 addTarget:self action:@selector(triggerEvent) forControlEvents:UIControlEventTouchUpInside]; __button1.frame = CGRectMake(20, 100, 100, 80); [self.view addSubview:__button1]; UIButton* __button2 = [UIButton buttonWithType:UIButtonTypeRoundedRect]; [__button2 setTitle:@"Stop RunLoop" forState:UIControlStateNormal]; //RunLoop週期完成後自動退出執行緒 [__button2 addTarget:self action:@selector(stopRunloop) forControlEvents:UIControlEventTouchUpInside]; __button2.frame = CGRectMake(130, 100, 120, 80); [self.view addSubview:__button2]; } - (void)stopRunloop{ _shouldStop = YES; } - (void)triggerEvent{ if (CFRunLoopIsWaiting(_runLoopRef)) { NSLog(@"RunLoop 正在等待事件輸入"); //新增輸入事件 CFRunLoopSourceSignal(_source); //喚醒執行緒,執行緒喚醒後發現由事件需要處理,於是立即處理事件 CFRunLoopWakeUp(_runLoopRef); }else { NSLog(@"RunLoop 正在處理事件"); //新增輸入事件,當前正在處理一個事件,當前事件處理完成後,立即處理當前新輸入的事件 CFRunLoopSourceSignal(_source); } } //此輸入源需要處理的後臺事件 static void fire(void* info __unused){ NSLog(@"我現在正在處理後臺任務"); sleep(5); } - (void)configRunLoop{ //這裡獲取到的已經是某個子執行緒了哦,不是主執行緒哦 _tThread = [NSThread currentThread]; //這裡也是這個子執行緒的RunLoop哦 _runLoopRef = CFRunLoopGetCurrent(); bzero(&_source_context, sizeof(_source_context)); //這裡建立了一個基於事件的源 _source_context.perform = fire; _source = CFRunLoopSourceCreate(NULL, 0, &_source_context); //將源新增到當前RunLoop中去 CFRunLoopAddSource(_runLoopRef, _source, kCFRunLoopCommonModes); while (!_shouldStop) { NSLog(@"RunLoop 開始執行"); //每次RunLoop只執行10秒,每10秒做一次檢測,如果沒有需要處理的後臺任務了,就讓此執行緒自己終止,不用暴力Kill CFRunLoopRunInMode(kCFRunLoopDefaultMode, 10, NO); NSLog(@"RunLoop 停止執行"); } _tThread = nil; } @end
CFRunLoopSourceRef _source;
CFRunLoopSourceContext _source_context;
NSThread* _tThread;
CFRunLoopRef _runLoopRef;
@interface ViewController : UIViewController{ CFRunLoopSourceRef _source; CFRunLoopSourceContext _source_context; NSThread* _tThread; CFRunLoopRef _runLoopRef; BOOL _shouldStop; } @end