RunLoop knowledge

NSRunLoop is a wrapper class for CFRunLoopRef

NSRunLoopisOCobject

CFRunLoopRefiscore FoundationDefinitions in the library

The state of the NSRunLoop

NSDefaultRunLoopMode // NsRunLoopCommonMode is not an actual state // but a set of NSDefaultRunLoopMode and UITrackingRunLoopMode  NSRunLoopCommonModesCopy the code

The state of the CFRunLoop

/* Run Loop Observer Activities */ typedef CF_OPTIONS(CFOptionFlags, CFRunLoopActivity) { kCFRunLoopEntry = (1UL << 0), KCFRunLoopBeforeTimers = (1UL << 1), // Timer kCFRunLoopBeforeSources = (1UL << 2), // Source kCFRunLoopBeforeWaiting = (1UL << 5), kCFRunLoopAfterWaiting = (1UL << 6), KCFRunLoopExit = (1UL << 7), // About to exit loop kCFRunLoopAllActivities = 0x0FFFFFFFU};Copy the code

RunLoopState monitoring

KCFRunLoopAllActivities Specifies the state to listen on. KCFRunLoopAllActivities specifies the state to listen on. KCFRunLoopAllActivities specifies the state to listen on CFRunLoopObserverRef observer = CFRunLoopObserverCreateWithHandler(CFAllocatorGetDefault(), kCFRunLoopAllActivities, YES, 0, ^(CFRunLoopObserverRef observer, CFRunLoopActivity activity) { /* kCFRunLoopEntry = (1UL << 0), Approaching runloop kCFRunLoopBeforeTimers = (1UL << 1), Timer event kCFRunLoopBeforeSources = (1UL << 2), Source event kCFRunLoopBeforeWaiting = (1UL << 5), going to sleep KCFRunLoopAfterWaiting = (1UL << 6), Runloop Exit kCFRunLoopAllActivities = 0x0FFFFFFFU */ Switch (activity) {case kCFRunLoopEntry: NSLog(@" about to enter runloop"); break; Case kCFRunLoopBeforeTimers: NSLog(@" About to process a timer event "); break; Case kCFRunLoopBeforeSources: NSLog(@" about to process source event "); break; Case kCFRunLoopBeforeWaiting: NSLog(@" going to sleep "); break; Case kCFRunLoopAfterWaiting: NSLog(@" awakened "); break; Case kCFRunLoopExit: NSLog(@"runloop exit "); break; default: break; }}); NSDefaultRunLoopMode == kCFRunLoopDefaultMode NSRunLoopCommonModes == kCFRunLoopCommonModes */ CFRunLoopAddObserver(CFRunLoopGetCurrent(),observer, kCFRunLoopDefaultMode); // Destroy the observer CFRelease(observer);Copy the code

OC version code implementation

//=======================.h=========================== #import <Foundation/Foundation.h> NS_ASSUME_NONNULL_BEGIN @interface PSKeepAliveThread: NSObject /// / @param Task Task block - (void)executeTask:(void (^)(void))task; // stopThread - (void)stopThread; @end NS_ASSUME_NONNULL_END //=======================.m=========================== #import "PSKeepAliveThread.h" @interface PSKeepAliveThread () @property (nonatomic, strong) NSThread *innerThread; @property (nonatomic, assign) BOOL isStop; @property (nonatomic, assign) BOOL isRun; @end @implementation PSKeepAliveThread - (instancetype)init { if (self = [super init]) { __weak typeof(self) weakSelf = self; Self. innerThread = [[NSThread alloc] initWithBlock:^{// thread start // get the runloop of the current thread, And to add a thread NSPort (source) [[NSRunLoop currentRunLoop] addPort: [[NSPort alloc] init] forMode: NSDefaultRunLoopMode]; // Use weak reference to ensure isStop variable can exit loop when set to YES while (weakSelf &&! Weakself. isStop) {// When the program runs to this point, if there is no task to execute, the thread will go to sleep and will not continue executing the while loop // until there is a task to execute, Will be awakened [[NSRunLoop currentRunLoop] runMode: NSDefaultRunLoopMode beforeDate: [NSDate distantFuture]].}} / / thread end]; // Start thread [self run]; } return self; } - (void)run { if (! self.isRun) { self.isRun = YES; [self.innerThread start]; }} - (void)executeTask:(void (^)(void))task {// do not execute the task if (! self.innerThread || ! task) return; / / put the task in the thread that executes [self performSelector: @ the selector (__executeTask:) onThread: self innerThread withObject: task waitUntilDone:NO]; } - (void)__executeTask:(void (^)(void))task { task(); } // stopThread - (void)stopThread {if (! self.innerThread) return; [self performSelector:@selector(__stopThread) onThread:self.innerThread withObject:nil waitUntilDone:YES]; } - (void)__stopThread { self.isStop = YES; self.isRun = NO; // Stop the current thread Runloop CFRunLoopStop(CFRunLoopGetCurrent()); self.innerThread = nil; } - (void)dealloc {// Stop the thread when the current class is released [self stopThread]; } @endCopy the code

C language version implementation

#import "PSKeepAliveThread.h" @interface PSKeepAliveThread () @property (nonatomic, strong) NSThread *innerThread; @property (nonatomic, assign) BOOL isRun; @end @implementation PSKeepAliveThread - (instancetype)init { if (self = [super init]) { self.innerThread = [[NSThread Alloc] initWithBlock:^{thread start // create context CFRunLoopSourceContext context = {0}; // create source CFRunLoopSourceRef source = CFRunLoopSourceCreate(kCFAllocatorDefault, 0, &context); // Add source CFRunLoopAddSource(CFRunLoopGetCurrent(), source, kCFRunLoopDefaultMode) to Runloop; // Run runloop and returnAfterSourceHandled: Loop CFRunLoopRunInMode(kCFRunLoopDefaultMode, 1.0e10, false); // Thread end}]; // Start thread [self run]; } return self; } - (void)run { if (! self.isRun) { self.isRun = YES; [self.innerThread start]; }} - (void)executeTask:(void (^)(void))task {// do not execute the task if (! self.innerThread || ! task) return; / / put the task in the thread that executes [self performSelector: @ the selector (__executeTask:) onThread: self innerThread withObject: task waitUntilDone:NO]; } - (void)__executeTask:(void (^)(void))task { task(); } // stopThread - (void)stopThread {if (! self.innerThread) return; [self performSelector:@selector(__stopThread) onThread:self.innerThread withObject:nil waitUntilDone:YES]; } - (void)__stopThread { self.isRun = NO; // Stop the current thread Runloop CFRunLoopStop(CFRunLoopGetCurrent()); self.innerThread = nil; } - (void)dealloc {// Stop the thread when the current class is released [self stopThread]; } @endCopy the code

use

#import "ViewController.h" #import "PSKeepAliveThread.h" @interface ViewController () @property (nonatomic, strong) PSKeepAliveThread *thread; @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; self.thread = [[PSKeepAliveThread alloc] init]; } - (void)touchesBegan:(NSSet< uittouch *> *) View withEvent:(UIEvent *) Event {[self.thread executeTask:^{NSLog(@"  %@", [NSThread currentThread]); }]; } // click the button to stop the thread - (IBAction)stopThreadAction:(UIButton *)sender {[self.thread stopThread]; } - (void)dealloc { NSLog(@"%s", __func__); [self.thread stopThread]; } @endCopy the code